From 52305ca91b49f8a8f0380234879ac4e5be1705fb Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 17 Jan 2019 14:45:53 -0800 Subject: more specific network checking in several places and remove some old debugging crud --- Zotlabs/Lib/Libzot.php | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 268622430..7dc6b411d 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -271,7 +271,7 @@ class Libzot { // correct hubloc. If this doesn't work we may have to re-write this section to try them all. if(array_key_exists('xchan_addr',$them) && $them['xchan_addr']) { - $r = q("select hubloc_id_url, hubloc_primary from hubloc where hubloc_addr = '%s' order by hubloc_id desc", + $r = q("select hubloc_id_url, hubloc_primary from hubloc where hubloc_addr = '%s' and hubloc_network = 'zot6' order by hubloc_id desc", dbesc($them['xchan_addr']) ); } @@ -356,7 +356,7 @@ class Libzot { ); if($r) { -logger('4'); + // connection exists // if the dob is the same as what we have stored (disregarding the year), keep the one @@ -1193,7 +1193,7 @@ logger('4'); //logger($AS->debug()); - $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1", + $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($AS->actor['id']) ); @@ -1202,7 +1202,7 @@ logger('4'); } - $s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1", + $s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($env['sender']) ); @@ -1512,10 +1512,12 @@ logger('4'); } } -logger('item: ' . print_r($arr,true), LOGGER_DATA); + logger('item: ' . print_r($arr,true), LOGGER_DATA); if($arr['mid'] !== $arr['parent_mid']) { -logger('checking source: "' . $arr['mid'] . '" != "' . $arr['parent_mid'] . '"'); + + logger('checking source: "' . $arr['mid'] . '" != "' . $arr['parent_mid'] . '"'); + // check source route. // We are only going to accept comments from this sender if the comment has the same route as the top-level-post, // this is so that permissions mismatches between senders apply to the entire conversation @@ -1600,7 +1602,7 @@ logger('checking source: "' . $arr['mid'] . '" != "' . $arr['parent_mid'] . '"') $arr['route'] = $last_prior_route; } } -logger('hey'); + $ab = q("select * from abook where abook_channel = %d and abook_xchan = '%s'", intval($channel['channel_id']), dbesc($arr['owner_xchan']) @@ -1778,14 +1780,14 @@ logger('hey'); logger($AS->debug()); - $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1", + $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($AS->actor['id']) ); if(! $r) { $y = import_author_xchan([ 'url' => $AS->actor['id'] ]); if($y) { - $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1", + $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($AS->actor['id']) ); } @@ -1808,7 +1810,7 @@ logger('hey'); $arr['author_xchan'] = $r[0]['hubloc_hash']; } - $s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1", + $s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($a['signature']['signer']) ); @@ -2593,7 +2595,7 @@ logger('hey'); $feed = ((x($arr,'feed')) ? intval($arr['feed']) : 0); if($ztarget) { - $t = q("select * from hubloc where hubloc_id_url = '%s' limit 1", + $t = q("select * from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($ztarget) ); if($t) { -- cgit v1.2.3 From 1b5dd8bbd7a751cf84f65403197d0dae5be4a8a0 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 20 Jan 2019 15:09:35 -0800 Subject: comment permission fix --- Zotlabs/Lib/Libzot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 7dc6b411d..00dd13afb 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1496,7 +1496,7 @@ class Libzot { intval($channel['channel_id']) ); if ($parent) { - $allowed = can_comment_on_post($d,$parent[0]); + $allowed = can_comment_on_post($sender,$parent[0]); } } if($request) { -- cgit v1.2.3 From b1e05b48327232d45275fb918252e9a3737b86e7 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Sat, 19 Jan 2019 23:13:16 +0100 Subject: Try to fix some warnings in Zotlabs\Module\Embedphotos. $phototypes was undefined, hope this is correct selection to fix it. Correct Doxygen and clean up some variables and refactoring. --- Zotlabs/Module/Embedphotos.php | 122 +++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 53 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Embedphotos.php b/Zotlabs/Module/Embedphotos.php index bcbb0e116..2df14c239 100644 --- a/Zotlabs/Module/Embedphotos.php +++ b/Zotlabs/Module/Embedphotos.php @@ -3,8 +3,10 @@ namespace Zotlabs\Module; /** - * @brief + * @brief Embedphoto endpoint. * + * Provide an AJAX endpoint to fill the embedPhotoModal with folders and photos + * selection. */ class Embedphotos extends \Zotlabs\Web\Controller { @@ -13,42 +15,42 @@ class Embedphotos extends \Zotlabs\Web\Controller { } /** + * @brief This is the POST destination for the embedphotos button. * - * This is the POST destination for the embedphotos button - * + * @return string A JSON string. */ - function post() { + public function post() { if (argc() > 1 && argv(1) === 'album') { // API: /embedphotos/album - $name = (x($_POST,'name') ? $_POST['name'] : null ); - if(!$name) { + $name = (x($_POST, 'name') ? $_POST['name'] : null ); + if (!$name) { json_return_and_die(array('errormsg' => 'Error retrieving album', 'status' => false)); } $album = $this->embedphotos_widget_album(array('channel' => \App::get_channel(), 'album' => $name)); json_return_and_die(array('status' => true, 'content' => $album)); } - if(argc() > 1 && argv(1) === 'albumlist') { + if (argc() > 1 && argv(1) === 'albumlist') { // API: /embedphotos/albumlist - $album_list = $this->embedphotos_album_list($a); + $album_list = $this->embedphotos_album_list(); json_return_and_die(array('status' => true, 'albumlist' => $album_list)); } - if(argc() > 1 && argv(1) === 'photolink') { + if (argc() > 1 && argv(1) === 'photolink') { // API: /embedphotos/photolink - $href = (x($_POST,'href') ? $_POST['href'] : null ); - if(!$href) { + $href = (x($_POST, 'href') ? $_POST['href'] : null ); + if (!$href) { json_return_and_die(array('errormsg' => 'Error retrieving link ' . $href, 'status' => false)); } - $resource_id = array_pop(explode("/", $href)); + $resource_id = array_pop(explode('/', $href)); $r = q("SELECT obj from item where resource_type = 'photo' and resource_id = '%s' limit 1", dbesc($resource_id) ); - if(!$r) { + if (!$r) { json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false)); } $obj = json_decode($r[0]['obj'], true); - if(x($obj,'body')) { + if (x($obj, 'body')) { $photolink = $obj['body']; - } elseif (x($obj,'bbcode')) { + } elseif (x($obj, 'bbcode')) { $photolink = $obj['bbcode']; } else { json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false)); @@ -58,48 +60,51 @@ class Embedphotos extends \Zotlabs\Web\Controller { } /** - * Copied from include/widgets.php::widget_album() with a modification to get the profile_uid from - * the input array as in widget_item() + * @brief Get photos from an album. + * + * @see \\Zotlabs\\Widget\\Album::widget() * - * @param array $args - * @return string with HTML + * @param array $args associative array with + * * \e array \b channel + * * \e string \b album + * @return string with HTML code from 'photo_album.tpl' */ - function embedphotos_widget_album($args) { - + protected function embedphotos_widget_album($args) { $channel_id = 0; - if(array_key_exists('channel', $args)) + + if (array_key_exists('channel', $args)) { $channel = $args['channel']; - $channel_id = intval($channel['channel_id']); - if(! $channel_id) + $channel_id = intval($channel['channel_id']); + } + if (! $channel_id) $channel_id = \App::$profile_uid; - if(! $channel_id) + if (! $channel_id) return ''; - $owner_uid = $channel_id; require_once('include/security.php'); $sql_extra = permissions_sql($channel_id); - if(! perm_is_allowed($channel_id,get_observer_hash(),'view_storage')) + if (! perm_is_allowed($channel_id, get_observer_hash(), 'view_storage')) return ''; - if($args['album']) + if (isset($args['album'])) $album = (($args['album'] === '/') ? '' : $args['album']); - if($args['title']) + if (isset($args['title'])) $title = $args['title']; /** - * This may return incorrect permissions if you have multiple directories of the same name. + * @note This may return incorrect permissions if you have multiple directories of the same name. * It is a limitation of the photo table using a name for a photo album instead of a folder hash */ - if($album) { + if ($album) { require_once('include/attach.php'); $x = q("select hash from attach where filename = '%s' and uid = %d limit 1", dbesc($album), - intval($owner_uid) + intval($channel_id) ); - if($x) { - $y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']); - if(! $y) + if ($x) { + $y = attach_can_view_folder($channel_id, get_observer_hash(), $x[0]['hash']); + if (! $y) return ''; } } @@ -110,30 +115,33 @@ class Embedphotos extends \Zotlabs\Web\Controller { (SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale) ORDER BY created $order", - intval($owner_uid), + intval($channel_id), dbesc($album), intval(PHOTO_NORMAL), intval(PHOTO_PROFILE) ); - $photos = array(); - if(count($r)) { + $photos = []; + if (count($r)) { $twist = 'rotright'; - foreach($r as $rr) { - if($twist == 'rotright') + foreach ($r as $rr) { + if ($twist == 'rotright') $twist = 'rotleft'; else $twist = 'rotright'; + $ph = photo_factory(''); + $phototypes = $ph->supportedTypes(); + $ext = $phototypes[$rr['mimetype']]; $imgalt_e = $rr['filename']; $desc_e = $rr['description']; - $imagelink = (z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id'] + $imagelink = (z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $rr['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '')); - $photos[] = array( + $photos[] = [ 'id' => $rr['id'], 'twist' => ' ' . $twist . rand(2,4), 'link' => $imagelink, @@ -143,35 +151,43 @@ class Embedphotos extends \Zotlabs\Web\Controller { 'desc'=> $desc_e, 'ext' => $ext, 'hash'=> $rr['resource_id'], - 'unknown' => t('Unknown') - ); + 'unknown' => t('Unknown'), + ]; } } $tpl = get_markup_template('photo_album.tpl'); - $o .= replace_macros($tpl, array( + $o = replace_macros($tpl, [ '$photos' => $photos, '$album' => (($title) ? $title : $album), '$album_id' => rand(), - '$album_edit' => array(t('Edit Album'), $album_edit), + '$album_edit' => array(t('Edit Album'), false), '$can_post' => false, '$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)), '$order' => false, - '$upload_form' => $upload_form, - '$no_fullscreen_btn' => true - )); + '$upload_form' => '', + '$no_fullscreen_btn' => true, + ]); return $o; } - function embedphotos_album_list($a) { + /** + * @brief Get albums observer is allowed to see. + * + * @see photos_albums_list() + * + * @return NULL|array + */ + protected function embedphotos_album_list() { require_once('include/photos.php'); $p = photos_albums_list(\App::get_channel(), \App::get_observer()); - if($p['success']) { + + if ($p['success']) { return $p['albums']; - } else { - return null; } + + return null; } } -- cgit v1.2.3 From cd8a0f33b5df4ae556bfcf274cfb3c4bd5fcdbf7 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Tue, 22 Jan 2019 12:13:16 +0100 Subject: Add remaining hook insertions --- Zotlabs/Module/Group.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index 3dcf903ad..12edf8428 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -66,6 +66,9 @@ class Group extends Controller { $groupname = notags(trim($_POST['groupname'])); $public = intval($_POST['public']); + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ]; + call_hooks ('privacygroup_extras_post',$hookinfo); + if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) { $r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d", dbesc($groupname), @@ -76,8 +79,6 @@ class Group extends Controller { if($r) info( t('Privacy group updated.') . EOL ); - $hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ]; - call_hooks ('privacygroup_extras_post',$hookinfo); build_sync_packet(local_channel(),null,true); } @@ -242,6 +243,10 @@ class Group extends Controller { } } + $hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ]; + call_hooks ('privacygroup_extras',$hookinfo); + $pgrp_extras = $hookinfo['pgrp_extras']; + $context = $context + array( '$title' => sprintf(t('Privacy Group: %s'), $group['gname']), '$details_label' => t('Edit'), @@ -252,6 +257,7 @@ class Group extends Controller { '$form_security_token_edit' => get_form_security_token('group_edit'), '$delete' => t('Delete Group'), '$form_security_token_drop' => get_form_security_token("group_drop"), + '$pgrp_extras' => $pgrp_extras, ); } @@ -295,6 +301,7 @@ class Group extends Controller { $context['$groupeditor'] = $groupeditor; $context['$desc'] = t('Click a channel to toggle membership'); + $context['$pgrp_extras'] = $pgrp_extras; if($change) { $tpl = get_markup_template('groupeditor.tpl'); -- cgit v1.2.3 From 13e0151cd2569832588cc9a973bcf40d850edd53 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Fri, 18 Jan 2019 22:17:10 +0100 Subject: Correct and extend Doxygen comments. Correct some documentation errors for Doxygen and add more comments. Document some undefined variables with @FIXME. --- Zotlabs/Lib/Libzot.php | 228 ++++++++++++++++++++++--------------------- Zotlabs/Lib/PConfig.php | 9 +- Zotlabs/Module/Cards.php | 16 +-- Zotlabs/Zot6/Zot6Handler.php | 36 +++---- 4 files changed, 146 insertions(+), 143 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index a0f6e077a..167e2d67d 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -2,11 +2,6 @@ namespace Zotlabs\Lib; -/** - * @brief lowlevel implementation of Zot6 protocol. - * - */ - use Zotlabs\Zot6\HTTPSig; use Zotlabs\Access\Permissions; use Zotlabs\Access\PermissionLimits; @@ -14,14 +9,17 @@ use Zotlabs\Daemon\Master; require_once('include/crypto.php'); - +/** + * @brief Lowlevel implementation of Zot6 protocol. + * + */ class Libzot { /** * @brief Generates a unique string for use as a zot guid. * - * Generates a unique string for use as a zot guid using our DNS-based url, the - * channel nickname and some entropy. + * Generates a unique string for use as a zot guid using our DNS-based url, + * the channel nickname and some entropy. * The entropy ensures uniqueness against re-installs where the same URL and * nickname are chosen. * @@ -32,9 +30,8 @@ class Libzot { * immediate universe. * * @param string $channel_nick a unique nickname of controlling entity - * @returns string + * @return string */ - static function new_uid($channel_nick) { $rawstr = z_root() . '/' . $channel_nick . '.' . mt_rand(); return(base64url_encode(hash('whirlpool', $rawstr, true), true)); @@ -52,8 +49,8 @@ class Libzot { * * @param string $guid * @param string $pubkey + * @return string */ - static function make_xchan_hash($guid, $pubkey) { return base64url_encode(hash('whirlpool', $guid . $pubkey, true)); } @@ -65,10 +62,8 @@ class Libzot { * should only be used by channels which are defined on this hub. * * @param string $hash - xchan_hash - * @returns array of hubloc (hub location structures) - * + * @return array of hubloc (hub location structures) */ - static function get_hublocs($hash) { /* Only search for active hublocs - e.g. those that haven't been marked deleted */ @@ -92,16 +87,17 @@ class Libzot { * packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'keychange', 'force_refresh', 'notify', 'auth_check' * @param array $recipients * envelope recipients, array of portable_id's; empty for public posts - * @param string msg + * @param string $msg * optional message + * @param string $encoding + * optional encoding, default 'activitystreams' * @param string $remote_key * optional public site key of target hub used to encrypt entire packet * NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others * @param string $methods - * optional comma separated list of encryption methods @ref self::best_algorithm() + * optional comma separated list of encryption methods @ref best_algorithm() * @returns string json encoded zot packet */ - static function build_packet($channel, $type = 'activity', $recipients = null, $msg = '', $encoding = 'activitystreams', $remote_key = null, $methods = '') { $sig_method = get_config('system','signature_algorithm','sha256'); @@ -146,11 +142,10 @@ class Libzot { * @brief Choose best encryption function from those available on both sites. * * @param string $methods - * comma separated list of encryption methods + * Comma separated list of encryption methods * @return string first match from our site method preferences crypto_methods() array - * of a method which is common to both sites; or 'aes256cbc' if no matches are found. + * of a method which is common to both sites; or 'aes256cbc' if no matches are found. */ - static function best_algorithm($methods) { $x = [ @@ -164,7 +159,6 @@ class Libzot { * * \e string \b methods - comma separated list of encryption methods * * \e string \b result - the algorithm to return */ - call_hooks('zot_best_algorithm', $x); if($x['result']) @@ -190,7 +184,7 @@ class Libzot { /** - * @brief send a zot message + * @brief Send a zot message. * * @see z_post_url() * @@ -200,18 +194,17 @@ class Libzot { * @param array $crypto (required if encrypted httpsig, requires hubloc_sitekey and site_crypto elements) * @return array see z_post_url() for returned data format */ - static function zot($url, $data, $channel = null,$crypto = null) { if($channel) { - $headers = [ - 'X-Zot-Token' => random_string(), - 'Digest' => HTTPSig::generate_digest_header($data), + $headers = [ + 'X-Zot-Token' => random_string(), + 'Digest' => HTTPSig::generate_digest_header($data), 'Content-type' => 'application/x-zot+json', '(request-target)' => 'post ' . get_request_string($url) ]; - $h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false,'sha512', + $h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false,'sha512', (($crypto) ? [ 'key' => $crypto['hubloc_sitekey'], 'algorithm' => self::best_algorithm($crypto['site_crypto']) ] : false)); } else { @@ -227,7 +220,6 @@ class Libzot { /** * @brief Refreshes after permission changed or friending, etc. * - * * refresh is typically invoked when somebody has changed permissions of a channel and they are notified * to fetch new permissions via a finger/discovery operation. This may result in a new connection * (abook entry) being added to a local channel and it may result in auto-permissions being granted. @@ -251,7 +243,6 @@ class Libzot { * * \b true if successful * * otherwise \b false */ - static function refresh($them, $channel = null, $force = false) { logger('them: ' . print_r($them,true), LOGGER_DATA, LOG_DEBUG); @@ -265,7 +256,7 @@ class Libzot { } else { $r = null; - + // if they re-installed the server we could end up with the wrong record - pointing to the old install. // We'll order by reverse id to try and pick off the newest one first and hopefully end up with the // correct hubloc. If this doesn't work we may have to re-write this section to try them all. @@ -317,6 +308,7 @@ class Libzot { if(! $hsig_valid) { logger('http signature not valid: ' . print_r($hsig,true)); + /// @FIXME $result is undefined return $result; } @@ -416,7 +408,7 @@ class Libzot { if($y) { logger("New introduction received for {$channel['channel_name']}"); $new_perms = get_all_perms($channel['channel_id'],$x['hash'],false); - + // Send a clone sync packet and a permissions update if permissions have changed $new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 order by abook_created desc limit 1", @@ -524,10 +516,14 @@ class Libzot { return false; } - - - - static function valid_hub($sender,$site_id) { + /** + * @brief + * + * @param string $sender + * @param string $site_id + * @return null|array + */ + static function valid_hub($sender, $site_id) { $r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and hubloc_site_id = '%s' limit 1", dbesc($sender), @@ -548,7 +544,6 @@ class Libzot { } return $r[0]; - } /** @@ -559,21 +554,14 @@ class Libzot { * origination address. This will fetch the discovery packet of the sender, * which contains the public key we need to verify our guid and url signatures. * - * @param array $arr an associative array which must contain: - * * \e string \b guid => guid of conversant - * * \e string \b guid_sig => guid signed with conversant's private key - * * \e string \b url => URL of the origination hub of this communication - * * \e string \b url_sig => URL signed with conversant's private key + * @param string $id * * @return array An associative array with - * * \b success boolean true or false - * * \b message (optional) error string only if success is false + * * \e boolean \b success + * * \e string \b message (optional, unused) error string only if success is false */ - static function register_hub($id) { - $id_hash = false; - $valid = false; $hsig_valid = false; $result = [ 'success' => false ]; @@ -807,7 +795,7 @@ class Libzot { // If setting for the default profile, unset the profile photo flag from any other photos I own if($is_default_profile) { - q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND resource_id != '%s' AND aid = %d AND uid = %d", + q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND resource_id != '%s' AND aid = %d AND uid = %d", intval(PHOTO_NORMAL), intval(PHOTO_PROFILE), dbesc($hash), @@ -954,8 +942,8 @@ class Libzot { * @param string $hub - url of site we just contacted * @param array $arr - output of z_post_url() * @param array $outq - The queue structure attached to this request + * @return void */ - static function process_response($hub, $arr, $outq) { logger('remote: ' . print_r($arr,true),LOGGER_DATA); @@ -986,7 +974,7 @@ class Libzot { if(! $x['success']) { // handle remote validation issues - + $b = q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'", dbesc(($x['message']) ? $x['message'] : 'unknown delivery error'), dbesc(datetime_convert()), @@ -994,7 +982,7 @@ class Libzot { ); } - if(is_array($x) && array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) { + if(is_array($x) && array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) { foreach($x['delivery_report'] as $xx) { call_hooks('dreport_process',$xx); @@ -1083,11 +1071,6 @@ class Libzot { * * @param array $arr * 'pickup' structure returned from remote site - * @param string $sender_url - * the url specified by the sender in the initial communication. - * We will verify the sender and url in each returned message structure and - * also verify that all the messages returned match the site url that we are - * currently processing. * * @returns array * Suitable for logging remotely, enumerating the processing results of each message/recipient combination @@ -1095,7 +1078,6 @@ class Libzot { * * [1] => \e string $delivery_status * * [2] => \e string $address */ - static function import($arr) { $env = $arr; @@ -1117,7 +1099,7 @@ class Libzot { $has_data = array_key_exists('data',$env) && $env['data']; $data = (($has_data) ? $env['data'] : false); - $AS = null; + $AS = null; if($env['encoding'] === 'activitystreams') { @@ -1175,7 +1157,6 @@ class Libzot { $deliveries = self::public_recips($env,$AS); - } $deliveries = array_unique($deliveries); @@ -1196,7 +1177,7 @@ class Libzot { $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($AS->actor['id']) - ); + ); if($r) { $arr['author_xchan'] = $r[0]['hubloc_hash']; @@ -1205,20 +1186,20 @@ class Libzot { $s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($env['sender']) - ); + ); // in individual delivery, change owner if needed if($s) { $arr['owner_xchan'] = $s[0]['hubloc_hash']; } else { - $arr['owner_xchan'] = $env['sender']; + $arr['owner_xchan'] = $env['sender']; } if($private) { $arr['item_private'] = true; } - // @fixme - spoofable + /// @FIXME - spoofable if($AS->data['hubloc']) { $arr['item_verified'] = true; } @@ -1247,12 +1228,19 @@ class Libzot { } if ($result) { $return = array_merge($return, $result); - } + } return $return; } - static function is_top_level($env,$act) { + /** + * @brief + * + * @param array $env + * @param object $act + * @return boolean + */ + static function is_top_level($env, $act) { if($env['encoding'] === 'zot' && array_key_exists('flags',$env) && in_array('thread_parent', $env['flags'])) { return true; } @@ -1295,9 +1283,9 @@ class Libzot { * Some of these will be rejected, but this gives us a place to start. * * @param array $msg - * @return NULL|array + * @param object $act + * @return array */ - static function public_recips($msg, $act) { require_once('include/channel.php'); @@ -1442,7 +1430,7 @@ class Libzot { * will normally arrive first via sync delivery, but this isn't guaranteed. * There's a chance the current delivery could take place before the cloned copy arrives * hence the item could have the wrong ACL and *could* be used in subsequent deliveries or - * access checks. + * access checks. */ if($sender === $channel['channel_portable_id'] && $arr['author_xchan'] === $channel['channel_portable_id'] && $arr['mid'] === $arr['parent_mid']) { @@ -1504,7 +1492,7 @@ class Libzot { $allowed = true; $friendofriend = true; } - + if (! $allowed) { logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}"); $DR->update('permission denied'); @@ -1524,7 +1512,7 @@ class Libzot { // this is so that permissions mismatches between senders apply to the entire conversation // As a side effect we will also do a preliminary check that we have the top-level-post, otherwise // processing it is pointless. - + $r = q("select route, id, owner_xchan, item_private from item where mid = '%s' and uid = %d limit 1", dbesc($arr['parent_mid']), intval($channel['channel_id']) @@ -1553,14 +1541,14 @@ class Libzot { } continue; } - + if($relay || $friendofriend || (intval($r[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) { // reset the route in case it travelled a great distance upstream // use our parent's route so when we go back downstream we'll match // with whatever route our parent has. // Also friend-of-friend conversations may have been imported without a route, // but we are now getting comments via listener delivery - // and if there is no privacy on this or the parent, we don't care about the route, + // and if there is no privacy on this or the parent, we don't care about the route, // so just set the owner and route accordingly. $arr['route'] = $r[0]['route']; $arr['owner_xchan'] = $r[0]['owner_xchan']; @@ -1614,13 +1602,13 @@ class Libzot { // remove_community_tag is a no-op if this isn't a community tag activity self::remove_community_tag($sender,$arr,$channel['channel_id']); - + // set these just in case we need to store a fresh copy of the deleted post. // This could happen if the delete got here before the original post did. $arr['aid'] = $channel['channel_account_id']; $arr['uid'] = $channel['channel_id']; - + $item_id = self::delete_imported_item($sender,$arr,$channel['channel_id'],$relay); $DR->update(($item_id) ? 'deleted' : 'delete_failed'); $result[] = $DR->get(); @@ -1716,7 +1704,7 @@ class Libzot { * * \e array \b item * * \e array \b sender * * \e array \b channel - */ + */ call_hooks('activity_received', $parr); // don't add a source route if it's a relay or later recipients will get a route mismatch if(! $relay) @@ -1783,7 +1771,7 @@ class Libzot { $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($AS->actor['id']) - ); + ); if(! $r) { $y = import_author_xchan([ 'url' => $AS->actor['id'] ]); @@ -1791,7 +1779,7 @@ class Libzot { $r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($AS->actor['id']) ); - } + } if(! $r) { logger('FOF Activity: no actor'); continue; @@ -1813,7 +1801,7 @@ class Libzot { $s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1", dbesc($a['signature']['signer']) - ); + ); if($s) { $arr['owner_xchan'] = $s[0]['hubloc_hash']; @@ -1822,7 +1810,7 @@ class Libzot { $arr['owner_xchan'] = $a['signature']['signer']; } - // @fixme - spoofable + /// @FIXME - spoofable if($AS->data['hubloc']) { $arr['item_verified'] = true; } @@ -1836,7 +1824,7 @@ class Libzot { $result = self::process_delivery($arr['owner_xchan'],$arr, [ $channel['channel_portable_id'] ],false,false,true); if ($result) { $ret = array_merge($ret, $result); - } + } } return $ret; @@ -1853,8 +1841,8 @@ class Libzot { * * \e int \b obj_type * * \e int \b mid * @param int $uid + * @return void */ - static function remove_community_tag($sender, $arr, $uid) { if(! (activity_match($arr['verb'], ACTIVITY_TAG) && ($arr['obj_type'] == ACTIVITY_OBJ_TAGTERM))) @@ -1882,7 +1870,7 @@ class Libzot { } $i = $r[0]; - + if($i['target']) $i['target'] = json_decode($i['target'],true); if($i['object']) @@ -1925,8 +1913,8 @@ class Libzot { * @param array $orig * @param int $uid * @param boolean $tag_delivery + * @return void|array */ - static function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) { // If this is a comment being updated, remove any privacy information @@ -2066,7 +2054,7 @@ class Libzot { } foreach($deliveries as $d) { - + $DR = new DReport(z_root(),$sender,$d,$arr['mid']); $r = q("select * from channel where channel_portable_id = '%s' limit 1", @@ -2085,7 +2073,7 @@ class Libzot { 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. @@ -2145,12 +2133,13 @@ class Libzot { * @brief Processes delivery of profile. * * @see import_directory_profile() + * * @param array $sender an associative array * * \e string \b hash a xchan_hash * @param array $arr * @param array $deliveries (unused) + * @return void */ - static function process_profile_delivery($sender, $arr, $deliveries) { logger('process_profile_delivery', LOGGER_DEBUG); @@ -2171,6 +2160,7 @@ class Libzot { * * \e string \b hash a xchan_hash * @param array $arr * @param array $deliveries (unused) deliveries is irrelevant + * @return void */ static function process_location_delivery($sender, $arr, $deliveries) { @@ -2188,7 +2178,7 @@ class Libzot { $x = Libsync::sync_locations($xchan,$arr,true); logger('results: ' . print_r($x,true), LOGGER_DEBUG); if($x['changed']) { - $guid = random_string() . '@' . App::get_hostname(); + //$guid = random_string() . '@' . App::get_hostname(); Libzotdir::update_modtime($sender,$r[0]['xchan_guid'],$arr['locations'][0]['address'],UPDATE_FLAGS_UPDATED); } } @@ -2212,8 +2202,8 @@ class Libzot { * * @param string $sender_hash A channel hash * @param array $locations + * @return void */ - static function check_location_move($sender_hash, $locations) { if(! $locations) @@ -2255,7 +2245,6 @@ class Libzot { } - /** * @brief Returns an array with all known distinct hubs for this channel. * @@ -2264,7 +2253,6 @@ class Libzot { * * \e string \b channel_hash the hash of the channel * @return array an array with associative arrays */ - static function encode_locations($channel) { $ret = []; @@ -2305,7 +2293,7 @@ class Libzot { if(! $z['site_id']) { $z['site_id'] = Libzot::make_xchan_hash($z['url'],$z['sitekey']); } - + $ret[] = $z; } } @@ -2318,10 +2306,8 @@ class Libzot { * @brief * * @param array $arr - * @param string $pubkey * @return boolean true if updated or inserted */ - static function import_site($arr) { if( (! is_array($arr)) || (! $arr['url']) || (! $arr['site_sig'])) @@ -2600,16 +2586,16 @@ class Libzot { dbesc($ztarget) ); if($t) { - + $ztarget_hash = $t[0]['hubloc_hash']; } else { - + // should probably perform discovery of the requestor (target) but if they actually had - // permissions we would know about them and we only want to know who they are to + // permissions we would know about them and we only want to know who they are to // enumerate their specific permissions - + $ztarget_hash = EMPTY_STR; } } @@ -2756,7 +2742,7 @@ class Libzot { $ret['id'] = $e['xchan_guid']; $ret['id_sig'] = self::sign($e['xchan_guid'], $e['channel_prvkey']); - $ret['primary_location'] = [ + $ret['primary_location'] = [ 'address' => $e['xchan_addr'], 'url' => $e['xchan_url'], 'connections_url' => $e['xchan_connurl'], @@ -2778,7 +2764,7 @@ class Libzot { $ret['searchable'] = $searchable; $ret['adult_content'] = $adult_channel; $ret['public_forum'] = $public_forum; - + $ret['comments'] = map_scope(PermissionLimits::Get($e['channel_id'],'post_comments')); $ret['mail'] = map_scope(PermissionLimits::Get($e['channel_id'],'post_mail')); @@ -2836,14 +2822,20 @@ class Libzot { $ret['locations'] = $x; $ret['site'] = self::site_info(); + /** + * @hooks zotinfo + * Hook to manipulate the zotinfo array before it is returned. + */ + call_hooks('zotinfo', $ret); - call_hooks('zotinfo',$ret); - - return($ret); - + return $ret; } - + /** + * @brief Get siteinfo. + * + * @return array + */ static function site_info() { $signing_key = get_config('system','prvkey'); @@ -2880,7 +2872,7 @@ class Libzot { if($dirmode != DIRECTORY_MODE_STANDALONE) { $register_policy = intval(get_config('system','register_policy')); - + if($register_policy == REGISTER_CLOSED) $ret['site']['register_policy'] = 'closed'; if($register_policy == REGISTER_APPROVE) @@ -2927,18 +2919,16 @@ class Libzot { } return $ret['site']; - } /** * @brief * * @param array $hub - * @param string $sitekey (optional, default empty) + * @param string $site_id (optional, default empty) * * @return string hubloc_url */ - static function update_hub_connected($hub, $site_id = '') { if ($site_id) { @@ -2997,12 +2987,21 @@ class Libzot { return $hub['hubloc_url']; } - + /** + * @brief + * + * @param string $data + * @param string $key + * @param string $alg (optional) default 'sha256' + * @return string + */ static function sign($data,$key,$alg = 'sha256') { if(! $key) return 'no key'; + $sig = ''; openssl_sign($data,$sig,$key,$alg); + return $alg . '.' . base64url_encode($sig); } @@ -3015,24 +3014,27 @@ class Libzot { if ($key && count($x) === 2) { $alg = $x[0]; $signature = base64url_decode($x[1]); - + $verify = @openssl_verify($data,$signature,$key,$alg); if ($verify === (-1)) { while ($msg = openssl_error_string()) { logger('openssl_verify: ' . $msg,LOGGER_NORMAL,LOG_ERR); } - btlogger('openssl_verify: key: ' . $key, LOGGER_DEBUG, LOG_ERR); + btlogger('openssl_verify: key: ' . $key, LOGGER_DEBUG, LOG_ERR); } } return(($verify > 0) ? true : false); } - - + /** + * @brief + * + * @return boolean + */ static function is_zot_request() { - $x = getBestSupportedMimeType([ 'application/x-zot+json' ]); + return(($x) ? true : false); } diff --git a/Zotlabs/Lib/PConfig.php b/Zotlabs/Lib/PConfig.php index 69f4de2db..95f07d580 100644 --- a/Zotlabs/Lib/PConfig.php +++ b/Zotlabs/Lib/PConfig.php @@ -112,9 +112,11 @@ class PConfig { * The configuration key to set * @param string $value * The value to store + * @param string $updated (optional) + * The datetime to store * @return mixed Stored $value or false */ - static public function Set($uid, $family, $key, $value, $updated=NULL) { + static public function Set($uid, $family, $key, $value, $updated = NULL) { // this catches subtle errors where this function has been called // with local_channel() when not logged in (which returns false) @@ -239,7 +241,9 @@ class PConfig { * The category of the configuration value * @param string $key * The configuration key to delete - * @return mixed + * @param string $updated (optional) + * The datetime to store + * @return boolean */ static public function Delete($uid, $family, $key, $updated = NULL) { @@ -283,6 +287,7 @@ class PConfig { if(! array_key_exists($family, \App::$config[$uid]['transient'])) \App::$config[$uid]['transient'][$family] = array(); + /// @FIXME $new is undefined, so dead code if ($new) { \App::$config[$uid]['transient'][$family]['pcfgdel:'.$key] = $updated; } diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index b66de158b..3f0e93de5 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -10,9 +10,13 @@ require_once('include/channel.php'); require_once('include/conversation.php'); require_once('include/acl_selectors.php'); +/** + * @brief Provides the Cards module. + * + */ class Cards extends Controller { - function init() { + public function init() { if(argc() > 1) $which = argv(1); @@ -20,14 +24,15 @@ class Cards extends Controller { return; profile_load($which); - } /** * {@inheritDoc} - * @see \Zotlabs\Web\Controller::get() + * @see \\Zotlabs\\Web\\Controller::get() + * + * @return string Parsed HTML from template 'cards.tpl' */ - function get($update = 0, $load = false) { + public function get($update = 0, $load = false) { if(observer_prohibited(true)) { return login(); @@ -99,7 +104,6 @@ class Cards extends Controller { } - if(perm_is_allowed($owner, $ob_hash, 'write_pages')) { $x = [ @@ -110,7 +114,7 @@ class Cards extends Controller { 'nickname' => $channel['channel_address'], 'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - 'acl' => (($is_owner) ? populate_acl($channel_acl, false, + 'acl' => (($is_owner) ? populate_acl($channel_acl, false, PermissionDescription::fromGlobalPermission('view_pages')) : ''), 'permissions' => $channel_acl, 'showacl' => (($is_owner) ? true : false), diff --git a/Zotlabs/Zot6/Zot6Handler.php b/Zotlabs/Zot6/Zot6Handler.php index e320e7825..8f8957037 100644 --- a/Zotlabs/Zot6/Zot6Handler.php +++ b/Zotlabs/Zot6/Zot6Handler.php @@ -29,7 +29,7 @@ class Zot6Handler implements IHandler { // Implementation of specific methods follows; - // These generally do a small amout of validation and call Libzot + // These generally do a small amout of validation and call Libzot // to do any heavy lifting static function reply_notify($data,$hub) { @@ -40,7 +40,7 @@ class Zot6Handler implements IHandler { $x = Libzot::fetch($data); $ret['delivery_report'] = $x; - + $ret['success'] = true; return $ret; @@ -58,11 +58,11 @@ class Zot6Handler implements IHandler { * * @param array $sender * @param array $recipients + * @param array $hub * - * @return json_return_and_die() + * @return array */ - - static function reply_refresh($sender, $recipients,$hub) { + static function reply_refresh($sender, $recipients, $hub) { $ret = array('success' => false); if($recipients) { @@ -70,19 +70,18 @@ class Zot6Handler implements IHandler { // This would be a permissions update, typically for one connection foreach ($recipients as $recip) { - $r = q("select channel.*,xchan.* from channel left join xchan on channel_portable_id = xchan_hash where xchan_hash ='%s' limit 1", dbesc($recip) ); - + /// @FIXME $msgtype is undefined $x = Libzot::refresh( [ 'hubloc_id_url' => $hub['hubloc_id_url'] ], $r[0], (($msgtype === 'force_refresh') ? true : false)); } } else { // system wide refresh - + /// @FIXME $msgtype is undefined $x = Libzot::refresh( [ 'hubloc_id_url' => $hub['hubloc_id_url'] ], null, (($msgtype === 'force_refresh') ? true : false)); } @@ -100,17 +99,16 @@ class Zot6Handler implements IHandler { * for that packet. We will create a message_list array of the entire conversation starting with * the missing parent and invoke delivery to the sender of the packet. * - * Zotlabs/Daemon/Deliver.php (for local delivery) and + * Zotlabs/Daemon/Deliver.php (for local delivery) and * mod/post.php???? @fixme (for web delivery) detect the existence of * this 'message_list' at the destination and split it into individual messages which are * processed/delivered in order. * - * * @param array $data + * @param array $hub * @return array */ - - static function reply_message_request($data,$hub) { + static function reply_message_request($data, $hub) { $ret = [ 'success' => false ]; $message_id = EMPTY_STR; @@ -153,11 +151,10 @@ class Zot6Handler implements IHandler { /* * fetch the requested conversation */ - + /// @FIXME $sender_hash is undefined $messages = zot_feed($c[0]['channel_id'],$sender_hash, [ 'message_id' => $data['message_id'], 'encoding' => 'activitystreams' ]); return (($messages) ? : [] ); - } static function rekey_request($sender,$data,$hub) { @@ -183,7 +180,7 @@ class Zot6Handler implements IHandler { dbesc($oldhash) ); } - else + else return $ret; @@ -219,10 +216,10 @@ class Zot6Handler implements IHandler { * * @param array $sender * @param array $recipients + * @param array $hub * - * return json_return_and_die() + * @return array */ - static function reply_purge($sender, $recipients, $hub) { $ret = array('success' => false); @@ -259,9 +256,4 @@ class Zot6Handler implements IHandler { return $ret; } - - - - - } -- cgit v1.2.3 From 32acf9cb7283f55338994346fd90c9ef2136fab3 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 24 Jan 2019 18:06:27 +0100 Subject: macke mod chanview aware of zot6 --- Zotlabs/Module/Chanview.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Chanview.php b/Zotlabs/Module/Chanview.php index 779c7e646..2e653d030 100644 --- a/Zotlabs/Module/Chanview.php +++ b/Zotlabs/Module/Chanview.php @@ -106,7 +106,7 @@ class Chanview extends \Zotlabs\Web\Controller { if (\App::$poi) { $url = \App::$poi['xchan_url']; - if(\App::$poi['xchan_network'] === 'zot') { + if(in_array(\App::$poi['xchan_network'], ['zot', 'zot6'])) { $is_zot = true; } if(local_channel()) { -- cgit v1.2.3 From 2fa274de1e567665c5fd3d25e382557eb4325d83 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 24 Jan 2019 19:08:57 -0800 Subject: support photo items between zot and zot6 --- Zotlabs/Daemon/Notifier.php | 2 ++ Zotlabs/Lib/Activity.php | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index beb30ed96..5ee8843b2 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -434,6 +434,8 @@ class Notifier { $x['body'] = 'private'; logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG); + //logger('notifier: encoded activity: ' . print_r($activity,true), LOGGER_DATA, LOG_DEBUG); + stringify_array_elms($recipients); if(! $recipients) { logger('no recipients'); diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index 154421b6a..03f094983 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -35,6 +35,9 @@ class Activity { if($x['type'] === ACTIVITY_OBJ_EVENT) { return self::fetch_event($x); } + if($x['type'] === ACTIVITY_OBJ_PHOTO) { + return self::fetch_image($x); + } return $x; @@ -102,6 +105,29 @@ class Activity { } } + + static function fetch_image($x) { + + + $ret = [ + 'type' => 'Image', + 'id' => $x['id'], + 'name' => $x['title'], + 'content' => bbcode($x['body']), + 'source' => [ 'mediaType' => 'text/bbcode', 'content' => $x['body'] ], + 'published' => datetime_convert('UTC','UTC',$x['created'],ATOM_TIME), + 'updated' => datetime_convert('UTC','UTC', $x['edited'],ATOM_TIME), + 'url' => [ + 'type' => 'Link', + 'mediaType' => $x['link'][0]['type'], + 'href' => $x['link'][0]['href'], + 'width' => $x['link'][0]['width'], + 'height' => $x['link'][0]['height'] + ] + ]; + return $ret; + } + static function fetch_event($x) { // convert old Zot event objects to ActivityStreams Event objects @@ -389,6 +415,8 @@ class Activity { } $ret['type'] = self::activity_mapper($i['verb']); + + $ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/activity/' . urlencode($i['mid'])); if($i['title']) @@ -460,6 +488,10 @@ class Activity { if(! is_array($i['obj'])) { $i['obj'] = json_decode($i['obj'],true); } + if($i['obj']['type'] === ACTIVITY_OBJ_PHOTO) { + $i['obj']['id'] = $i['id']; + } + $obj = self::encode_object($i['obj']); if($obj) $ret['object'] = $obj; @@ -1609,7 +1641,9 @@ class Activity { } - if($act->obj['type'] === 'Image') { + // avoid double images from hubzilla to zap/osada + + if($act->obj['type'] === 'Image' && strpos($s['body'],'zrl=') === false) { $ptr = null; -- cgit v1.2.3 From 10587e3a842d7870c94bd52c23dedc5abc114bdc Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 25 Jan 2019 10:49:17 +0100 Subject: return false if http signatue is not valid --- Zotlabs/Lib/Libzot.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 167e2d67d..1440a9691 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -308,8 +308,7 @@ class Libzot { if(! $hsig_valid) { logger('http signature not valid: ' . print_r($hsig,true)); - /// @FIXME $result is undefined - return $result; + return false; } -- cgit v1.2.3 From 37b7dc8e7c10870021c835168a441788f0fcb351 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Sun, 27 Jan 2019 17:36:56 +0100 Subject: Remove extraneous sync logic --- Zotlabs/Lib/PConfig.php | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/PConfig.php b/Zotlabs/Lib/PConfig.php index 95f07d580..c08c11e75 100644 --- a/Zotlabs/Lib/PConfig.php +++ b/Zotlabs/Lib/PConfig.php @@ -275,23 +275,13 @@ class PConfig { dbesc($key) ); + // Synchronize delete with clones. + if ($family != 'hz_delpconfig') { $hash = hash('sha256',$family.':'.$key); set_pconfig($uid,'hz_delpconfig',$hash,$updated); } - // Synchronize delete with clones. - - if(! array_key_exists('transient', \App::$config[$uid])) - \App::$config[$uid]['transient'] = array(); - if(! array_key_exists($family, \App::$config[$uid]['transient'])) - \App::$config[$uid]['transient'][$family] = array(); - - /// @FIXME $new is undefined, so dead code - if ($new) { - \App::$config[$uid]['transient'][$family]['pcfgdel:'.$key] = $updated; - } - return $ret; } -- cgit v1.2.3 From 94cbc8bd3160bf644b02ef97268244869b7a9f5b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 27 Jan 2019 12:38:51 -0800 Subject: share fixes --- Zotlabs/Lib/Activity.php | 5 +++++ Zotlabs/Lib/Share.php | 1 + 2 files changed, 6 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index 03f094983..8cfa18997 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -411,6 +411,11 @@ class Activity { $ret['type'] = 'Tombstone'; $ret['formerType'] = self::activity_obj_mapper($i['obj_type']); $ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid'])); + $actor = self::encode_person($i['author'],false); + if($actor) + $ret['actor'] = $actor; + else + return []; return $ret; } diff --git a/Zotlabs/Lib/Share.php b/Zotlabs/Lib/Share.php index d3ecbf7fa..3a2ab1783 100644 --- a/Zotlabs/Lib/Share.php +++ b/Zotlabs/Lib/Share.php @@ -54,6 +54,7 @@ class Share { if(! $this->item) return $obj; + $obj['asld'] = $this->item['mid']; $obj['type'] = $this->item['obj_type']; $obj['id'] = $this->item['mid']; $obj['content'] = $this->item['body']; -- cgit v1.2.3 From 625cdde9a40d13b47a794c6202add2c8f647aebe Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 28 Jan 2019 02:46:45 -0800 Subject: block private reshares from zot6 due to different parents --- Zotlabs/Daemon/Notifier.php | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 5ee8843b2..df73d977d 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -679,6 +679,17 @@ class Notifier { } $packet_type = (($upstream || $uplink) ? 'response' : 'activity'); + + // block zot private reshares from zot6, as this could cause a number of privacy issues + // due to parenting differences between the reshare implementations. In zot a reshare is + // a standalone parent activity and in zot6 it is a followup/child of the original activity. + // For public reshares, some comments to the reshare on the zot fork will not make it to zot6 + // due to these different message models. This cannot be prevented at this time. + + if($packet_type === 'activity' && $activity['type'] === 'Announce' && intval($target_item['item_private'])) { + continue; + } + $packet = Libzot::build_packet($channel,$packet_type,$zenv,$activity,'activitystreams',(($private) ? $hub['hubloc_sitekey'] : null),$hub['site_crypto']); } else { -- cgit v1.2.3 From 8972ca8134c16039c03ad83d26b75b9e9e21d7ea Mon Sep 17 00:00:00 2001 From: "DM42.Net (Matt Dent)" Date: Mon, 28 Jan 2019 14:20:46 -0500 Subject: Make session handler pluggable --- Zotlabs/Web/Session.php | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/Session.php b/Zotlabs/Web/Session.php index 4f2a3f1f7..1ba120fa9 100644 --- a/Zotlabs/Web/Session.php +++ b/Zotlabs/Web/Session.php @@ -15,6 +15,7 @@ class Session { private $handler = null; private $session_started = false; + private $custom_handler = false; public function init() { @@ -28,13 +29,20 @@ class Session { * Set our session storage functions. */ - $handler = new \Zotlabs\Web\SessionHandler(); + $custom_handler = $this->custom_handler; + call_hook('custom_session_handler',$custom_handler); + $this->custom_handler = $custom_handler; - $this->handler = $handler; - $x = session_set_save_handler($handler,false); - if(! $x) - logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); + if (!$this->custom_handler) { + $handler = new \Zotlabs\Web\SessionHandler(); + + $this->handler = $handler; + + $x = session_set_save_handler($handler,false); + if(! $x) + logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); + } // Force cookies to be secure (https only) if this site is SSL enabled. // Must be done before session_start(). @@ -86,14 +94,17 @@ class Session { $arr = session_get_cookie_params(); - if($this->handler && $this->session_started) { + if(($this->handler || $this->custom_handler) && $this->session_started) { session_regenerate_id(true); - // force SessionHandler record creation with the new session_id - // which occurs as a side effect of read() + if (!$this->custom_handler) { + // force SessionHandler record creation with the new session_id + // which occurs as a side effect of read() since not all implementations + // of session_regenerate_id() call read(). - $this->handler->read(session_id()); + $this->handler->read(session_id()); + } } else logger('no session handler'); -- cgit v1.2.3 From 728788e3b9ce351b7eab0fba00e97ba59215e975 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Sat, 26 Jan 2019 00:47:39 +0100 Subject: Extend documentation. --- Zotlabs/Lib/Apps.php | 375 ++++++++++++++++++++++++++++++----------------- Zotlabs/Module/Notes.php | 20 +-- 2 files changed, 249 insertions(+), 146 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index de7439ed7..9edd00667 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -1,32 +1,34 @@ - t('Remote Diagnostics'), 'Suggest Channels' => t('Suggest Channels'), 'Login' => t('Login'), - 'Channel Manager' => t('Channel Manager'), + 'Channel Manager' => t('Channel Manager'), 'Network' => t('Stream'), 'Settings' => t('Settings'), 'Files' => t('Files'), 'Webpages' => t('Webpages'), 'Wiki' => t('Wiki'), - 'Channel Home' => t('Channel Home'), + 'Channel Home' => t('Channel Home'), 'View Profile' => t('View Profile'), - 'Photos' => t('Photos'), - 'Events' => t('Events'), - 'Directory' => t('Directory'), + 'Photos' => t('Photos'), + 'Events' => t('Events'), + 'Directory' => t('Directory'), 'Help' => t('Help'), 'Mail' => t('Mail'), 'Mood' => t('Mood'), @@ -366,30 +385,31 @@ class Apps { if(array_key_exists($arr[$x]['name'],$apps)) { $arr[$x]['name'] = $apps[$arr[$x]['name']]; } else { - // Try to guess by app name if not in list - $arr[$x]['name'] = t(trim($arr[$x]['name'])); + // Try to guess by app name if not in list + $arr[$x]['name'] = t(trim($arr[$x]['name'])); } } } - } - - // papp is a portable app - - static public function app_render($papp,$mode = 'view') { - - /** - * modes: - * view: normal mode for viewing an app via bbcode from a conversation or page - * provides install/update button if you're logged in locally - * install: like view but does not display app-bin options if they are present - * list: normal mode for viewing an app on the app page - * no buttons are shown - * edit: viewing the app page in editing mode provides a delete button - * nav: render apps for app-bin - */ - + /** + * @brief + * + * @param array $papp + * papp is a portable app + * @param string $mode (optional) default 'view' + * Render modes: + * * \b view: normal mode for viewing an app via bbcode from a conversation or page + * provides install/update button if you're logged in locally + * * \b install: like view but does not display app-bin options if they are present + * * \b list: normal mode for viewing an app on the app page + * no buttons are shown + * * \b edit: viewing the app page in editing mode provides a delete button + * * \b nav: render apps for app-bin + * + * @return void|string Parsed HTML + */ + static public function app_render($papp, $mode = 'view') { $installed = false; if(! $papp) @@ -414,7 +434,7 @@ class Apps { $sys = get_sys_channel(); $view_channel = $sys['channel_id']; } - self::app_macros($view_channel,$papp); + self::app_macros($view_channel,$papp); } if(strpos($papp['url'], ',')) { @@ -427,7 +447,6 @@ class Apps { $papp['url'] = z_root() . ((strpos($papp['url'],'/') === 0) ? '' : '/') . $papp['url']; - foreach($papp as $k => $v) { if(strpos($v,'http') === 0 && $k != 'papp') { if(! (local_channel() && strpos($v,z_root()) === 0)) { @@ -509,7 +528,7 @@ class Apps { if($x) { $hosturl = $x['scheme'] . '://' . $x['host'] . '/'; } - } + } } $install_action = (($installed) ? t('Update') : t('Install')); @@ -592,8 +611,14 @@ class Apps { return false; } - - static public function can_delete($uid,$app) { + /** + * @brief + * + * @param mixed $uid If not set return false, otherwise no influence + * @param array $app + * @return boolean + */ + static public function can_delete($uid, $app) { if(! $uid) { return false; } @@ -601,7 +626,7 @@ class Apps { $base_apps = self::get_base_apps(); if($base_apps) { foreach($base_apps as $b) { - if($app['guid'] === hash('whirlpool',$b)) { + if($app['guid'] === hash('whirlpool', $b)) { return false; } } @@ -613,7 +638,6 @@ class Apps { static public function app_destroy($uid,$app) { if($uid && $app['guid']) { - $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1", dbesc($app['guid']), intval($uid) @@ -622,7 +646,7 @@ class Apps { if(! intval($x[0]['app_deleted'])) { $x[0]['app_deleted'] = 1; if(self::can_delete($uid,$app)) { - $r = q("delete from app where app_id = '%s' and app_channel = %d", + q("delete from app where app_id = '%s' and app_channel = %d", dbesc($app['guid']), intval($uid) ); @@ -630,10 +654,15 @@ class Apps { intval(TERM_OBJ_APP), intval($x[0]['id']) ); + /** + * @hooks app_destroy + * Called after app entry got removed from database + * and provide app array from database. + */ call_hooks('app_destroy', $x[0]); } else { - $r = q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d", + q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d", dbesc($app['guid']), intval($uid) ); @@ -647,22 +676,23 @@ class Apps { } } } - } - static public function app_undestroy($uid,$app) { - - // undelete a system app - + /** + * @brief Undelete a system app. + * + * @param int $uid + * @param array $app + */ + static public function app_undestroy($uid, $app) { if($uid && $app['guid']) { - $x = q("select * from app where app_id = '%s' and app_channel = %d limit 1", dbesc($app['guid']), intval($uid) ); if($x) { if($x[0]['app_system']) { - $r = q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d", + q("update app set app_deleted = 0 where app_id = '%s' and app_channel = %d", dbesc($app['guid']), intval($uid) ); @@ -671,7 +701,15 @@ class Apps { } } - static public function app_feature($uid,$app,$term) { + /** + * @brief + * + * @param int $uid + * @param array $app + * @param string $term + * @return void + */ + static public function app_feature($uid, $app, $term) { $r = q("select id from app where app_id = '%s' and app_channel = %d limit 1", dbesc($app['guid']), intval($uid) @@ -695,23 +733,37 @@ class Apps { } } - static public function app_installed($uid,$app,$bypass_filter=false) { + /** + * @brief + * + * @param int $uid + * @param array $app + * @param boolean $bypass_filter (optional) default false + * @return boolean + */ + static public function app_installed($uid, $app, $bypass_filter = false) { $r = q("select id from app where app_id = '%s' and app_channel = %d limit 1", - dbesc((array_key_exists('guid',$app)) ? $app['guid'] : ''), + dbesc((array_key_exists('guid', $app)) ? $app['guid'] : ''), intval($uid) ); - if (!$bypass_filter) { + if(!$bypass_filter) { $filter_arr = [ - 'uid'=>$uid, - 'app'=>$app, - 'installed'=>$r + 'uid' => $uid, + 'app' => $app, + 'installed' => $r ]; - call_hooks('app_installed_filter',$filter_arr); + /** + * @hooks app_installed_filter + * * \e int \b uid + * * \e array \b app + * * \e mixed \b installed - return value + */ + call_hooks('app_installed_filter', $filter_arr); $r = $filter_arr['installed']; } - return(($r) ? true : false); + return(($r) ? true : false); } @@ -727,11 +779,17 @@ class Apps { 'app'=>$app, 'installed'=>$r ]; - call_hooks('addon_app_installed_filter',$filter_arr); + /** + * @hooks addon_app_installed_filter + * * \e int \b uid + * * \e array \b app + * * \e mixed \b installed - return value + */ + call_hooks('addon_app_installed_filter', $filter_arr); $r = $filter_arr['installed']; } - return(($r) ? true : false); + return(($r) ? true : false); } static public function system_app_installed($uid,$app,$bypass_filter=false) { @@ -746,28 +804,39 @@ class Apps { 'app'=>$app, 'installed'=>$r ]; - call_hooks('system_app_installed_filter',$filter_arr); + /** + * @hooks system_app_installed_filter + * * \e int \b uid + * * \e array \b app + * * \e mixed \b installed - return value + */ + call_hooks('system_app_installed_filter', $filter_arr); $r = $filter_arr['installed']; } - return(($r) ? true : false); + return(($r) ? true : false); } - - + /** + * @brief + * + * @param int $uid + * @param boolean $deleted + * @param array $cats + * @return boolean|array + */ static public function app_list($uid, $deleted = false, $cats = []) { - if($deleted) - $sql_extra = ""; + if($deleted) + $sql_extra = ''; else - $sql_extra = " and app_deleted = 0 "; + $sql_extra = ' and app_deleted = 0 '; if($cats) { - - $cat_sql_extra = " and ( "; + $cat_sql_extra = ' and ( '; foreach($cats as $cat) { if(strpos($cat_sql_extra, 'term')) - $cat_sql_extra .= "or "; + $cat_sql_extra .= 'or '; $cat_sql_extra .= "term = '" . dbesc($cat) . "' "; } @@ -779,11 +848,13 @@ class Apps { ); if(! $r) return $r; - $sql_extra .= " and app.id in ( "; + + $sql_extra .= ' and app.id in ( '; $s = ''; foreach($r as $rr) { if($s) $s .= ','; + $s .= intval($rr['oid']); } $sql_extra .= $s . ') '; @@ -794,12 +865,26 @@ class Apps { ); if($r) { - $hookinfo = Array('uid'=>$uid,'deleted'=>$deleted,'cats'=>$cats,'apps'=>$r); - call_hooks('app_list',$hookinfo); + $hookinfo = [ + 'uid' => $uid, + 'deleted' => $deleted, + 'cats' => $cats, + 'apps' => $r, + ]; + /** + * @hooks app_list + * * \e int \b uid + * * \e boolean \b deleted + * * \e array \b cats + * * \e array \b apps - return value + */ + call_hooks('app_list', $hookinfo); $r = $hookinfo['apps']; - for($x = 0; $x < count($r); $x ++) { + + for($x = 0; $x < count($r); $x++) { if(! $r[$x]['app_system']) $r[$x]['type'] = 'personal'; + $r[$x]['term'] = q("select * from term where otype = %d and oid = %d", intval(TERM_OBJ_APP), intval($r[$x]['id']) @@ -807,7 +892,7 @@ class Apps { } } - return($r); + return $r; } static public function app_order($uid,$apps,$menu) { @@ -839,13 +924,14 @@ class Apps { $ret[] = $ap; } } - return $ret; + return $ret; } static function find_app_in_array($name,$arr) { if(! $arr) return false; + foreach($arr as $x) { if($x['name'] === $name) { return $x; @@ -854,8 +940,16 @@ class Apps { return false; } - static function moveup($uid,$guid,$menu) { - $syslist = array(); + /** + * @brief + * + * @param int $uid + * @param int $guid + * @param string $menu + * @return void + */ + static function moveup($uid, $guid, $menu) { + $syslist = []; $conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order'); @@ -865,6 +959,7 @@ class Apps { $papp = self::app_encode($li); if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false) continue; + $syslist[] = $papp; } } @@ -877,8 +972,6 @@ class Apps { if(! $syslist) return; - $newlist = []; - foreach($syslist as $k => $li) { if($li['guid'] === $guid) { $position = $k; @@ -887,6 +980,7 @@ class Apps { } if(! $position) return; + $dest_position = $position - 1; $saved = $syslist[$dest_position]; $syslist[$dest_position] = $syslist[$position]; @@ -898,11 +992,18 @@ class Apps { } set_pconfig($uid,'system',$conf,implode(',',$narr)); - } - static function movedown($uid,$guid,$menu) { - $syslist = array(); + /** + * @brief + * + * @param int $uid + * @param int $guid + * @param string $menu + * @return void + */ + static function movedown($uid, $guid, $menu) { + $syslist = []; $conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order'); @@ -912,6 +1013,7 @@ class Apps { $papp = self::app_encode($li); if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false) continue; + $syslist[] = $papp; } } @@ -924,8 +1026,6 @@ class Apps { if(! $syslist) return; - $newlist = []; - foreach($syslist as $k => $li) { if($li['guid'] === $guid) { $position = $k; @@ -934,6 +1034,7 @@ class Apps { } if($position >= count($syslist) - 1) return; + $dest_position = $position + 1; $saved = $syslist[$dest_position]; $syslist[$dest_position] = $syslist[$position]; @@ -945,7 +1046,6 @@ class Apps { } set_pconfig($uid,'system',$conf,implode(',',$narr)); - } static public function app_decode($s) { @@ -953,8 +1053,14 @@ class Apps { return json_decode($x,true); } - - static public function app_macros($uid,&$arr) { + /** + * @brief + * + * @param int $uid + * @param[in,out] array $arr + * @return void + */ + static public function app_macros($uid, &$arr) { if(! intval($uid)) return; @@ -962,21 +1068,17 @@ class Apps { $baseurl = z_root(); $channel = channelx_by_n($uid); $address = (($channel) ? $channel['channel_address'] : ''); - + //future expansion - $observer = \App::get_observer(); - + //$observer = \App::get_observer(); + $arr['url'] = str_replace(array('$baseurl','$nick'),array($baseurl,$address),$arr['url']); $arr['photo'] = str_replace(array('$baseurl','$nick'),array($baseurl,$address),$arr['photo']); - } - - - static public function app_store($arr) { //logger('app_store: ' . print_r($arr,true)); @@ -1160,16 +1262,20 @@ class Apps { } return $ret; - } - - static public function app_encode($app,$embed = false) { - - $ret = array(); + /** + * @brief + * + * @param array $app + * @param boolean $embed (optional) default false + * @return array|string + */ + static public function app_encode($app, $embed = false) { + $ret = []; $ret['type'] = 'personal'; - + if($app['app_id']) $ret['guid'] = $app['app_id']; @@ -1202,7 +1308,7 @@ class Apps { if($app['app_price']) $ret['price'] = $app['app_price']; - + if($app['app_page']) $ret['page'] = $app['app_page']; @@ -1226,12 +1332,12 @@ class Apps { foreach($app['term'] as $t) { if($s) $s .= ','; + $s .= $t['term']; } $ret['categories'] = $s; } - if(! $embed) return $ret; @@ -1239,18 +1345,15 @@ class Apps { if(array_key_exists('categories',$ret)) unset($ret['categories']); - + $j = json_encode($ret); - return '[app]' . chunk_split(base64_encode($j),72,"\n") . '[/app]'; + return '[app]' . chunk_split(base64_encode($j),72,"\n") . '[/app]'; } static public function papp_encode($papp) { return chunk_split(base64_encode(json_encode($papp)),72,"\n"); - } } - - diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php index 178a6bce0..7572f7420 100644 --- a/Zotlabs/Module/Notes.php +++ b/Zotlabs/Module/Notes.php @@ -1,28 +1,31 @@ true); if(array_key_exists('note_text',$_REQUEST)) { $body = escape_tags($_REQUEST['note_text']); - + // I've had my notes vanish into thin air twice in four years. - // Provide a backup copy if there were contents previously + // Provide a backup copy if there were contents previously // and there are none being saved now. - + if(! $body) { $old_text = get_pconfig(local_channel(),'notes','text'); if($old_text) @@ -40,11 +43,9 @@ class Notes extends Controller { logger('notes saved.', LOGGER_DEBUG); json_return_and_die($ret); - } function get() { - if(! local_channel()) return EMPTY_STR; @@ -61,7 +62,6 @@ class Notes extends Controller { $arr = ['app' => true]; return $w->widget($arr); - } - + } -- cgit v1.2.3 From 753f137575674a4fb1cfb16753baced6ed21145a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 28 Jan 2019 15:29:39 -0800 Subject: disable hyperdrive in hubzilla --- Zotlabs/Lib/Libzot.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 1440a9691..27502009c 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1534,6 +1534,11 @@ class Libzot { // the top level post is unlikely to be imported and // this is just an exercise in futility. + + if((! get_pconfig($channel['channel_id'],'system','hyperdrive',false)) || (! $arr['verb'] === 'Announce')) { + continue; + } + if((! $relay) && (! $request) && (! $local_public) && perm_is_allowed($channel['channel_id'],$sender,'send_stream')) { self::fetch_conversation($channel,$arr['parent_mid']); -- cgit v1.2.3 From 456207b4e75ee4b28b60e90b44ef758dc95b2ebc Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 29 Jan 2019 10:13:49 +0100 Subject: fix wrong function name and coding style --- Zotlabs/Web/Session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/Session.php b/Zotlabs/Web/Session.php index 1ba120fa9..648f6b720 100644 --- a/Zotlabs/Web/Session.php +++ b/Zotlabs/Web/Session.php @@ -30,7 +30,7 @@ class Session { */ $custom_handler = $this->custom_handler; - call_hook('custom_session_handler',$custom_handler); + call_hooks('custom_session_handler', $custom_handler); $this->custom_handler = $custom_handler; -- cgit v1.2.3 From cd4d90c6479dad05e08faca2e9bbedc9b7710858 Mon Sep 17 00:00:00 2001 From: Mario Date: Tue, 29 Jan 2019 21:16:16 +0100 Subject: Revert "fix wrong function name and coding style" This reverts commit 456207b4e75ee4b28b60e90b44ef758dc95b2ebc --- Zotlabs/Web/Session.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/Session.php b/Zotlabs/Web/Session.php index 648f6b720..1ba120fa9 100644 --- a/Zotlabs/Web/Session.php +++ b/Zotlabs/Web/Session.php @@ -30,7 +30,7 @@ class Session { */ $custom_handler = $this->custom_handler; - call_hooks('custom_session_handler', $custom_handler); + call_hook('custom_session_handler',$custom_handler); $this->custom_handler = $custom_handler; -- cgit v1.2.3 From 913b620c66f32a4c89acbadfc4fdf751d3a34b17 Mon Sep 17 00:00:00 2001 From: Mario Date: Tue, 29 Jan 2019 21:16:38 +0100 Subject: Revert "Make session handler pluggable" This reverts commit 8972ca8134c16039c03ad83d26b75b9e9e21d7ea --- Zotlabs/Web/Session.php | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/Session.php b/Zotlabs/Web/Session.php index 1ba120fa9..4f2a3f1f7 100644 --- a/Zotlabs/Web/Session.php +++ b/Zotlabs/Web/Session.php @@ -15,7 +15,6 @@ class Session { private $handler = null; private $session_started = false; - private $custom_handler = false; public function init() { @@ -29,20 +28,13 @@ class Session { * Set our session storage functions. */ - $custom_handler = $this->custom_handler; - call_hook('custom_session_handler',$custom_handler); - $this->custom_handler = $custom_handler; + $handler = new \Zotlabs\Web\SessionHandler(); + $this->handler = $handler; - if (!$this->custom_handler) { - $handler = new \Zotlabs\Web\SessionHandler(); - - $this->handler = $handler; - - $x = session_set_save_handler($handler,false); - if(! $x) - logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); - } + $x = session_set_save_handler($handler,false); + if(! $x) + logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); // Force cookies to be secure (https only) if this site is SSL enabled. // Must be done before session_start(). @@ -94,17 +86,14 @@ class Session { $arr = session_get_cookie_params(); - if(($this->handler || $this->custom_handler) && $this->session_started) { + if($this->handler && $this->session_started) { session_regenerate_id(true); - if (!$this->custom_handler) { - // force SessionHandler record creation with the new session_id - // which occurs as a side effect of read() since not all implementations - // of session_regenerate_id() call read(). + // force SessionHandler record creation with the new session_id + // which occurs as a side effect of read() - $this->handler->read(session_id()); - } + $this->handler->read(session_id()); } else logger('no session handler'); -- cgit v1.2.3 From 4b516fdb0927021dc4ebb38513127699e48b87f9 Mon Sep 17 00:00:00 2001 From: Mark Nowiasz Date: Tue, 29 Jan 2019 21:41:23 +0100 Subject: Custom sessionhandler support, as requested --- Zotlabs/Web/Session.php | 50 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/Session.php b/Zotlabs/Web/Session.php index 4f2a3f1f7..31979c3f6 100644 --- a/Zotlabs/Web/Session.php +++ b/Zotlabs/Web/Session.php @@ -15,7 +15,7 @@ class Session { private $handler = null; private $session_started = false; - + private $custom_handler = false; public function init() { $gc_probability = 50; @@ -23,25 +23,44 @@ class Session { ini_set('session.gc_probability', $gc_probability); ini_set('session.use_only_cookies', 1); ini_set('session.cookie_httponly', 1); - + + $this->custom_handler = boolval(get_config('system', 'session_custom', false)); + /* * Set our session storage functions. */ - - $handler = new \Zotlabs\Web\SessionHandler(); - - $this->handler = $handler; - - $x = session_set_save_handler($handler,false); - if(! $x) - logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); - + + if ($this->custom_handler) { + /* Custom handler (files, memached, redis..) */ + + $session_save_handler = strval(get_config('system', 'session_save_handler', Null)); + $session_save_path = strval(get_config('system', 'session_save_path', Null)); + $session_gc_probability = intval(get_config('system', 'session_gc_probability', 1)); + $session_gc_divisor = intval(get_config('system', 'session_gc_divisor', 100)); + if (!$session_save_handler || !$session_save_path) { + logger('Session save handler or path not set.',LOGGER_NORMAL,LOG_ERR); + } else { + ini_set('session.save_handler', $session_save_handler); + ini_set('session.save_path', $session_save_path); + ini_set('session.gc_probability', $session_gc_probability); + ini_set('session.gc_divisor', $session_gc_divisor); + + } + } else { + $handler = new \Zotlabs\Web\SessionHandler(); + + $this->handler = $handler; + + $x = session_set_save_handler($handler,false); + if(! $x) + logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); + }; // Force cookies to be secure (https only) if this site is SSL enabled. // Must be done before session_start(). $arr = session_get_cookie_params(); - + // Note when setting cookies: set the domain to false which creates a single domain // cookie. If you use a hostname it will create a .domain.com wildcard which will // have some nasty side effects if you have any other subdomains running hubzilla. @@ -86,14 +105,15 @@ class Session { $arr = session_get_cookie_params(); - if($this->handler && $this->session_started) { + if(($this->handler || $this->custom_handler) && $this->session_started) { session_regenerate_id(true); // force SessionHandler record creation with the new session_id // which occurs as a side effect of read() - - $this->handler->read(session_id()); + if (! $this->custom_handler) { + $this->handler->read(session_id()); + } } else logger('no session handler'); -- cgit v1.2.3 From 3b31dbaa169345e95580e40c809d3cf3f0b642c2 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 29 Jan 2019 22:37:30 +0100 Subject: clean up whitespace and remove superfluous semicolon --- Zotlabs/Web/Session.php | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/Session.php b/Zotlabs/Web/Session.php index 31979c3f6..fe0a3fbf9 100644 --- a/Zotlabs/Web/Session.php +++ b/Zotlabs/Web/Session.php @@ -30,23 +30,24 @@ class Session { * Set our session storage functions. */ - if ($this->custom_handler) { - /* Custom handler (files, memached, redis..) */ - - $session_save_handler = strval(get_config('system', 'session_save_handler', Null)); - $session_save_path = strval(get_config('system', 'session_save_path', Null)); - $session_gc_probability = intval(get_config('system', 'session_gc_probability', 1)); - $session_gc_divisor = intval(get_config('system', 'session_gc_divisor', 100)); - if (!$session_save_handler || !$session_save_path) { - logger('Session save handler or path not set.',LOGGER_NORMAL,LOG_ERR); - } else { - ini_set('session.save_handler', $session_save_handler); - ini_set('session.save_path', $session_save_path); - ini_set('session.gc_probability', $session_gc_probability); - ini_set('session.gc_divisor', $session_gc_divisor); - - } - } else { + if($this->custom_handler) { + /* Custom handler (files, memached, redis..) */ + + $session_save_handler = strval(get_config('system', 'session_save_handler', Null)); + $session_save_path = strval(get_config('system', 'session_save_path', Null)); + $session_gc_probability = intval(get_config('system', 'session_gc_probability', 1)); + $session_gc_divisor = intval(get_config('system', 'session_gc_divisor', 100)); + if(!$session_save_handler || !$session_save_path) { + logger('Session save handler or path not set.',LOGGER_NORMAL,LOG_ERR); + } + else { + ini_set('session.save_handler', $session_save_handler); + ini_set('session.save_path', $session_save_path); + ini_set('session.gc_probability', $session_gc_probability); + ini_set('session.gc_divisor', $session_gc_divisor); + } + } + else { $handler = new \Zotlabs\Web\SessionHandler(); $this->handler = $handler; @@ -54,7 +55,8 @@ class Session { $x = session_set_save_handler($handler,false); if(! $x) logger('Session save handler initialisation failed.',LOGGER_NORMAL,LOG_ERR); - }; + } + // Force cookies to be secure (https only) if this site is SSL enabled. // Must be done before session_start(). -- cgit v1.2.3 From b15421826d91d7344ad28a16f0be047c191d5ec4 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 29 Jan 2019 15:14:49 -0800 Subject: cache embeds in the background on initial storage rather than on first access --- Zotlabs/Daemon/Cache_embeds.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Zotlabs/Daemon/Cache_embeds.php (limited to 'Zotlabs') diff --git a/Zotlabs/Daemon/Cache_embeds.php b/Zotlabs/Daemon/Cache_embeds.php new file mode 100644 index 000000000..08088abd6 --- /dev/null +++ b/Zotlabs/Daemon/Cache_embeds.php @@ -0,0 +1,27 @@ + Date: Thu, 31 Jan 2019 18:39:07 +0100 Subject: starring and filing is only supported for post item type --- Zotlabs/Lib/ThreadItem.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 83d243177..dc84df316 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -411,9 +411,9 @@ class ThreadItem { 'rawmid' => $item['mid'], 'plink' => get_plink($item), 'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''), - 'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts')) ? $star : ''), + 'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts') && ($item['item_type'] == ITEM_TYPE_POST)) ? $star : ''), 'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''), - 'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''), + 'filer' => ((feature_enabled($conv->get_profile_owner(),'filing') && ($item['item_type'] == ITEM_TYPE_POST)) ? $filer : ''), 'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''), 'addtocal' => (($has_event) ? t('Add to Calendar') : ''), 'drop' => $drop, -- cgit v1.2.3 From ad4dd2def58999c58fc12def0e6b5789597f5581 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Fri, 1 Feb 2019 09:29:59 +0100 Subject: Set lock red and provide warning if a forum is tagged in the post --- Zotlabs/Lib/ThreadItem.php | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index dc84df316..7ce0d0f9e 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -101,6 +101,7 @@ class ThreadItem { || strlen($item['deny_cid']) || strlen($item['deny_gid'])))) ? t('Private Message') : false); + $shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false); // allow an exemption for sharing stuff from your private feeds @@ -115,6 +116,16 @@ class ThreadItem { $privacy_warning = true; } + if ($lock) { + if (count(get_terms_oftype($item['term'],TERM_FORUM))) { + $privacy_warning = true; + } + } + + if ($lock && $privacy_warning) { + $lock = t('Privacy conflict. Discretion advised.'); + } + $mode = $conv->get_mode(); switch($item['item_type']) { -- cgit v1.2.3 From 4706ff693843e0fd059bba5d306a172f059b4af7 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sun, 3 Feb 2019 14:52:50 +0100 Subject: do not overwrite $sql_extra --- Zotlabs/Module/Oep.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php index 0f20a5f9a..491a48f28 100644 --- a/Zotlabs/Module/Oep.php +++ b/Zotlabs/Module/Oep.php @@ -181,7 +181,7 @@ class Oep extends \Zotlabs\Web\Controller { dbesc($res) ); if($r) { - $sql_extra = "and item.id = " . intval($r[0]['iid']) . " "; + $sql_extra .= " and item.id = " . intval($r[0]['iid']) . " "; } else { return $ret; @@ -255,6 +255,8 @@ class Oep extends \Zotlabs\Web\Controller { if(! $channel) return $ret; +hz_syslog($nick); + if(! perm_is_allowed($channel['channel_id'],get_observer_hash(),'view_pages')) return $ret; @@ -265,7 +267,7 @@ class Oep extends \Zotlabs\Web\Controller { dbesc($res) ); if($r) { - $sql_extra = "and item.id = " . intval($r[0]['iid']) . " "; + $sql_extra .= " and item.id = " . intval($r[0]['iid']) . " "; } else { return $ret; -- cgit v1.2.3 From c657d766cf0dbca750840a4395003ea9e94a4809 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sun, 3 Feb 2019 14:58:19 +0100 Subject: cleanup logging and return if query returns empty result --- Zotlabs/Module/Oep.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oep.php b/Zotlabs/Module/Oep.php index 491a48f28..c0d8e15e5 100644 --- a/Zotlabs/Module/Oep.php +++ b/Zotlabs/Module/Oep.php @@ -194,6 +194,9 @@ class Oep extends \Zotlabs\Web\Controller { intval(ITEM_TYPE_CARD) ); + if(! $r) + return; + $item_normal = " and item.item_hidden = 0 and item.item_type in (0,6) and item.item_deleted = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 and item.item_blocked = 0 "; @@ -255,9 +258,6 @@ class Oep extends \Zotlabs\Web\Controller { if(! $channel) return $ret; -hz_syslog($nick); - - if(! perm_is_allowed($channel['channel_id'],get_observer_hash(),'view_pages')) return $ret; @@ -280,6 +280,9 @@ hz_syslog($nick); intval(ITEM_TYPE_ARTICLE) ); + if(! $r) + return; + $item_normal = " and item.item_hidden = 0 and item.item_type in (0,7) and item.item_deleted = 0 and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0 and item.item_blocked = 0 "; -- cgit v1.2.3 From 8dcf27ba29089fdcc0b917ebd26e5c5190dc9d7b Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sun, 3 Feb 2019 21:12:09 +0100 Subject: add the actual mid for debuging reasons --- Zotlabs/Module/Viewsrc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Viewsrc.php b/Zotlabs/Module/Viewsrc.php index 119990b57..b73d81283 100644 --- a/Zotlabs/Module/Viewsrc.php +++ b/Zotlabs/Module/Viewsrc.php @@ -28,7 +28,7 @@ class Viewsrc extends \Zotlabs\Web\Controller { $item_normal = item_normal(); if(local_channel() && $item_id) { - $r = q("select id, item_flags, mimetype, item_obscured, body, llink, plink from item where uid in (%d , %d) and id = %d $item_normal limit 1", + $r = q("select id, mid, item_flags, mimetype, item_obscured, body, llink, plink from item where uid in (%d , %d) and id = %d $item_normal limit 1", intval(local_channel()), intval($sys['channel_id']), intval($item_id) @@ -53,7 +53,7 @@ class Viewsrc extends \Zotlabs\Web\Controller { if(is_ajax()) { echo '
'; - echo '
id: ' . $r[0]['id'] . ' | plink | llink
'; + echo '
id: ' . $r[0]['id'] . ' | plink | llink
mid: ' . $r[0]['mid'] . '
'; echo '
'; echo '
' . $o . '
'; echo '
'; -- cgit v1.2.3 From 8ff9a9ff08db1a6e821b9d74c0a58e8ced174d9b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 3 Feb 2019 16:53:49 -0800 Subject: fix linkify_tags() so it works with xchans across multiple protocols, also some fixes to activity parsing from upstream. --- Zotlabs/Lib/Activity.php | 7 +++++-- Zotlabs/Module/Admin/Site.php | 2 +- Zotlabs/Module/Events.php | 4 ++-- Zotlabs/Module/Item.php | 4 ++-- Zotlabs/Module/Mail.php | 4 ++-- Zotlabs/Module/Photos.php | 2 +- Zotlabs/Module/Profiles.php | 28 ++++++++++++++-------------- 7 files changed, 27 insertions(+), 24 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index 8cfa18997..259419f54 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -1411,6 +1411,9 @@ class Activity { $s['owner_xchan'] = $act->actor['id']; $s['author_xchan'] = $act->actor['id']; + // ensure we store the original actor + self::actor_store($act->actor['id'],$act->actor); + $s['mid'] = $act->obj['id']; $s['parent_mid'] = $act->parent_id; @@ -1483,7 +1486,8 @@ class Activity { $s['verb'] = self::activity_decode_mapper($act->type); - if($act->type === 'Tombstone') { + + if($act->type === 'Tombstone' || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) { $s['item_deleted'] = 1; } @@ -1492,7 +1496,6 @@ class Activity { $s['obj_type'] = ACTIVITY_OBJ_COMMENT; } - if($act->obj['type'] === 'Event') { $s['obj'] = []; $s['obj']['asld'] = $act->obj; diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index 09b038729..55c8ca928 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -119,7 +119,7 @@ class Site { del_config('system', 'admininfo'); } else { require_once('include/text.php'); - linkify_tags($a, $admininfo, local_channel()); + linkify_tags($admininfo, local_channel()); set_config('system', 'admininfo', $admininfo); } set_config('system','siteinfo',$siteinfo); diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php index 7e5204e62..e883db49f 100644 --- a/Zotlabs/Module/Events.php +++ b/Zotlabs/Module/Events.php @@ -97,8 +97,8 @@ class Events extends \Zotlabs\Web\Controller { $type = escape_tags(trim($_POST['type'])); require_once('include/text.php'); - linkify_tags($a, $desc, local_channel()); - linkify_tags($a, $location, local_channel()); + linkify_tags($desc, local_channel()); + linkify_tags($location, local_channel()); //$action = ($event_hash == '') ? 'new' : "event/" . $event_hash; diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 24949c626..a48a25e03 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -553,8 +553,8 @@ class Item extends Controller { // Look for tags and linkify them - $results = linkify_tags($a, $summary, ($uid) ? $uid : $profile_uid); - $results = linkify_tags($a, $body, ($uid) ? $uid : $profile_uid); + $results = linkify_tags($summary, ($uid) ? $uid : $profile_uid); + $results = linkify_tags($body, ($uid) ? $uid : $profile_uid); if($results) { diff --git a/Zotlabs/Module/Mail.php b/Zotlabs/Module/Mail.php index d38c1d88c..3202d38a5 100644 --- a/Zotlabs/Module/Mail.php +++ b/Zotlabs/Module/Mail.php @@ -34,7 +34,7 @@ class Mail extends \Zotlabs\Web\Controller { } else { $body = cleanup_bbcode($body); - $results = linkify_tags($a, $body, local_channel()); + $results = linkify_tags($body, local_channel()); if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) { $attachments = array(); @@ -111,7 +111,7 @@ class Mail extends \Zotlabs\Web\Controller { } require_once('include/text.php'); - linkify_tags($a, $body, local_channel()); + linkify_tags($body, local_channel()); if(! $recipient) { diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 3833d5088..a761dbd14 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -422,7 +422,7 @@ class Photos extends \Zotlabs\Web\Controller { require_once('include/text.php'); $profile_uid = \App::$profile['profile_uid']; - $results = linkify_tags($a, $rawtags, (local_channel()) ? local_channel() : $profile_uid); + $results = linkify_tags($rawtags, (local_channel()) ? local_channel() : $profile_uid); $success = $results['success']; $post_tags = array(); diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php index de4075ba9..33e7d8a9d 100644 --- a/Zotlabs/Module/Profiles.php +++ b/Zotlabs/Module/Profiles.php @@ -354,20 +354,20 @@ class Profiles extends \Zotlabs\Web\Controller { require_once('include/text.php'); - linkify_tags($a, $likes, local_channel()); - linkify_tags($a, $dislikes, local_channel()); - linkify_tags($a, $about, local_channel()); - linkify_tags($a, $interest, local_channel()); - linkify_tags($a, $interest, local_channel()); - linkify_tags($a, $contact, local_channel()); - linkify_tags($a, $channels, local_channel()); - linkify_tags($a, $music, local_channel()); - linkify_tags($a, $book, local_channel()); - linkify_tags($a, $tv, local_channel()); - linkify_tags($a, $film, local_channel()); - linkify_tags($a, $romance, local_channel()); - linkify_tags($a, $work, local_channel()); - linkify_tags($a, $education, local_channel()); + linkify_tags($likes, local_channel()); + linkify_tags($dislikes, local_channel()); + linkify_tags($about, local_channel()); + linkify_tags($interest, local_channel()); + linkify_tags($interest, local_channel()); + linkify_tags($contact, local_channel()); + linkify_tags($channels, local_channel()); + linkify_tags($music, local_channel()); + linkify_tags($book, local_channel()); + linkify_tags($tv, local_channel()); + linkify_tags($film, local_channel()); + linkify_tags($romance, local_channel()); + linkify_tags($work, local_channel()); + linkify_tags($education, local_channel()); $with = ((x($_POST,'with')) ? escape_tags(trim($_POST['with'])) : ''); -- cgit v1.2.3 From 518ceb53a8de5b4ee375947721d56f7a43621a61 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 5 Feb 2019 14:51:01 -0800 Subject: allow conversation completion for new comments to expired posts, regardless of hyperdrive settings. Note that hyperdrive conversations may still be fetched from zap/osada servers but will be ignored. --- Zotlabs/Lib/Libzot.php | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 27502009c..189526c7b 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1487,8 +1487,31 @@ class Libzot { $allowed = can_comment_on_post($sender,$parent[0]); } } - if($request) { - $allowed = true; + + if ($request) { + + // Conversation fetches (e.g. $request == true) take place for + // a) new comments on expired posts + // b) hyperdrive (friend-of-friend) conversations + // c) Repeats of posts by others + + + // over-ride normal connection permissions for hyperdrive (friend-of-friend) conversations + // (if hyperdrive is enabled) and repeated posts by a friend. + // If $allowed is already true, this is probably the conversation of a direct friend or a + // conversation fetch for a new comment on an expired post + // Comments of all these activities are allowed and will only be rejected (later) if the parent + // doesn't exist. + + if ($perm === 'send_stream') { + if (get_pconfig($channel['channel_id'],'system','hyperdrive',false) || $arr['verb'] === 'Announce') { + $allowed = true; + } + } + else { + $allowed = true; + } + $friendofriend = true; } @@ -1500,7 +1523,7 @@ class Libzot { } } - logger('item: ' . print_r($arr,true), LOGGER_DATA); + // logger('item: ' . print_r($arr,true), LOGGER_DATA); if($arr['mid'] !== $arr['parent_mid']) { @@ -1526,19 +1549,11 @@ class Libzot { // have the copy and we don't want the request to loop. // Also don't do this if this comment came from a conversation request packet. // It's possible that comments are allowed but posting isn't and that could - // cause a conversation fetch loop. We can detect these packets since they are - // delivered via a 'notify' packet type that has a message_id element in the - // initial zot packet (just like the corresponding 'request' packet type which - // makes the request). + // cause a conversation fetch loop. // We'll also check the send_stream permission - because if it isn't allowed, // the top level post is unlikely to be imported and // this is just an exercise in futility. - - if((! get_pconfig($channel['channel_id'],'system','hyperdrive',false)) || (! $arr['verb'] === 'Announce')) { - continue; - } - if((! $relay) && (! $request) && (! $local_public) && perm_is_allowed($channel['channel_id'],$sender,'send_stream')) { self::fetch_conversation($channel,$arr['parent_mid']); @@ -1814,6 +1829,7 @@ class Libzot { $arr['owner_xchan'] = $a['signature']['signer']; } + /// @FIXME - spoofable if($AS->data['hubloc']) { $arr['item_verified'] = true; -- cgit v1.2.3 From 29c1797493f44d2677cab9b35ce6d879f020a15e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 6 Feb 2019 17:26:09 -0800 Subject: work on repeat/share for Hubzilla --- Zotlabs/Lib/Activity.php | 2 +- Zotlabs/Lib/ThreadItem.php | 7 ++- Zotlabs/Module/Embed.php | 22 ++++++++ Zotlabs/Module/Share.php | 134 +++++++++++++++++++++++++++------------------ 4 files changed, 110 insertions(+), 55 deletions(-) create mode 100644 Zotlabs/Module/Embed.php (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php index 259419f54..bcbe53df7 100644 --- a/Zotlabs/Lib/Activity.php +++ b/Zotlabs/Lib/Activity.php @@ -236,7 +236,7 @@ class Activity { $ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid'])); if($i['title']) - $ret['title'] = bbcode($i['title']); + $ret['name'] = $i['title']; $ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME); if($i['created'] !== $i['edited']) diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 83d243177..6c4deea27 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -293,8 +293,10 @@ class ThreadItem { $dislike = array( t("I don't like this \x28toggle\x29"), t("dislike")); } - if ($shareable) - $share = array( t('Share This'), t('share')); + if ($shareable) { + $share = array( t('Repeat This'), t('repeat')); + $embed = array( t('Share This'), t('share')); + } $dreport = ''; @@ -408,6 +410,7 @@ class ThreadItem { 'like' => $like, 'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''), 'share' => $share, + 'embed' => $embed, 'rawmid' => $item['mid'], 'plink' => get_plink($item), 'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''), diff --git a/Zotlabs/Module/Embed.php b/Zotlabs/Module/Embed.php new file mode 100644 index 000000000..77b9254dd --- /dev/null +++ b/Zotlabs/Module/Embed.php @@ -0,0 +1,22 @@ + 1) ? intval(argv(1)) : 0); + + if(! $post_id) + killme(); + + echo '[share=' . $post_id . '][/share]'; + killme(); + + } + +} diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index c6d0be051..af339a09b 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -1,6 +1,10 @@ '', 'body' => $o )); - killme(); + call_hooks('post_local_end', $arr); + + info( t('Post repeated') . EOL); + + $r = q("select * from item where id = %d", + intval($post_id) + ); + if($r) { + xchan_query($r); + $sync_item = fetch_post_tags($r); + build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]); } + + Master::Summon([ 'Notifier','like',$post_id ]); + + killme(); + } } -- cgit v1.2.3 From 96a4fc7ca27da2d1ad864bd05f7d2165a037677d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 6 Feb 2019 19:26:28 -0800 Subject: more work on share/repeat --- Zotlabs/Module/Share.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index af339a09b..58b70318d 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -3,6 +3,7 @@ namespace Zotlabs\Module; use App; use Zotlabs\Daemon\Master; +use Zotlabs\Lib\Activity; require_once('include/security.php'); @@ -98,7 +99,7 @@ class Share extends \Zotlabs\Web\Controller { $arr['parent_mid'] = $item['mid']; $mention = '@[zrl=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/zrl]'; - $arr['body'] = sprintf( t('🔁 Repeated %1$s\'s %2$s'), $mention, $item['obj_type']); + $arr['body'] = sprintf( t('🔁 Repeated %1$s\'s %2$s'), $mention, Activity::activity_obj_mapper($item['obj_type'])); $arr['author_xchan'] = $channel['channel_hash']; $arr['owner_xchan'] = $item['author_xchan']; -- cgit v1.2.3 From 7f6e4a9744b7b5293e1f0d25db8bb3ad17cd256d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 6 Feb 2019 19:59:05 -0800 Subject: fix verb for reshares --- Zotlabs/Module/Item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index a48a25e03..f19d4907b 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -639,9 +639,9 @@ class Item extends Controller { if(preg_match_all('/(\[share=(.*?)\](.*?)\[\/share\])/',$body,$match)) { + // process share by id - $verb = ACTIVITY_SHARE; $i = 0; foreach($match[2] as $mtch) { $reshare = new \Zotlabs\Lib\Share($mtch); -- cgit v1.2.3 From beb26e84f3698106bd145ff21a7477e1775397dd Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 7 Feb 2019 11:18:34 -0800 Subject: fix mid generation for shares --- Zotlabs/Module/Share.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index 58b70318d..dcb2343ce 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -94,8 +94,8 @@ class Share extends \Zotlabs\Web\Controller { $arr['item_origin'] = 1; $arr['item_wall'] = $item['item_wall']; - $arr['mid'] = item_message_id(); - $arr['mid'] = str_replace('/item/','/activity/',$arr['mid']); + $arr['uuid'] = item_message_id(); + $arr['mid'] = z_root() . '/activity/' . $arr['uuid']; $arr['parent_mid'] = $item['mid']; $mention = '@[zrl=' . $item['author']['xchan_url'] . ']' . $item['author']['xchan_name'] . '[/zrl]'; -- cgit v1.2.3 From 92e6c21210b71acb2e1071171fa8cd7e76640f7b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 7 Feb 2019 14:13:13 -0800 Subject: add missing zot6 conversation completion (required for message repeats) --- Zotlabs/Lib/ThreadListener.php | 53 +++++++++++++++ Zotlabs/Module/Item.php | 144 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 Zotlabs/Lib/ThreadListener.php (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadListener.php b/Zotlabs/Lib/ThreadListener.php new file mode 100644 index 000000000..ad682aac8 --- /dev/null +++ b/Zotlabs/Lib/ThreadListener.php @@ -0,0 +1,53 @@ + [ + ACTIVITYSTREAMS_JSONLD_REV, + 'https://w3id.org/security/v1', + z_root() . ZOT_APSCHEMA_REV + ]], $i); + + $headers = []; + $headers['Content-Type'] = 'application/x-zot+json' ; + $x['signature'] = LDSignatures::sign($x,$chan); + $ret = json_encode($x, JSON_UNESCAPED_SLASHES); + $headers['Digest'] = HTTPSig::generate_digest_header($ret); + $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; + $h = HTTPSig::create_sig($headers,$chan['channel_prvkey'],channel_url($chan)); + HTTPSig::set_headers($h); + echo $ret; + killme(); + + } + } + + + function post() { // This will change. Figure out who the observer is and whether or not -- cgit v1.2.3 From f02af5fe6ea9e86a99e6e1ae5a7057350bb7224a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 7 Feb 2019 14:25:25 -0800 Subject: automatically redirect repeat to share for posts with unresolvable message-ids (diaspora, hz < 4.0, etc.). --- Zotlabs/Module/Share.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index dcb2343ce..cca72f12f 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -27,13 +27,15 @@ class Share extends \Zotlabs\Web\Controller { $channel = App::get_channel(); - $r = q("SELECT * from item left join xchan on author_xchan = xchan_hash WHERE id = %d LIMIT 1", intval($post_id) ); if(! $r) killme(); + + + if(($r[0]['item_private']) && ($r[0]['xchan_network'] !== 'rss')) killme(); @@ -49,8 +51,12 @@ class Share extends \Zotlabs\Web\Controller { if($r[0]['mimetype'] !== 'text/bbcode') killme(); - - + + if(strpos($r[0]['mid'],'http') === false) { + notice( t('Source message cannot be repeated. Sharing instead.') . EOL); + goaway(z_root() . '/embed/' . argv(1)); + } + xchan_query($r); $arr = []; -- cgit v1.2.3 From 317c53acf6b74a4f92284074017985fb09662a46 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 7 Feb 2019 14:38:05 -0800 Subject: disable repeat unless mid is a resolvable uri since this will do radically different things on different network stacks (e.g. Diaspora) and it turns out there is no possible way to make Diaspora reshares compatible with ActivityPub or Zot6 repeat/announce/boost/whatever. --- Zotlabs/Lib/ThreadItem.php | 6 +++++- Zotlabs/Module/Share.php | 5 ----- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 6c4deea27..94d0e3cf8 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -294,7 +294,11 @@ class ThreadItem { } if ($shareable) { - $share = array( t('Repeat This'), t('repeat')); + // This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues. + // Will allow it only for uri resolvable sources. + if(strpos($item['mid'],'http') === 0) { + $share = array( t('Repeat This'), t('repeat')); + } $embed = array( t('Share This'), t('share')); } diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index cca72f12f..53a06b072 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -51,11 +51,6 @@ class Share extends \Zotlabs\Web\Controller { if($r[0]['mimetype'] !== 'text/bbcode') killme(); - - if(strpos($r[0]['mid'],'http') === false) { - notice( t('Source message cannot be repeated. Sharing instead.') . EOL); - goaway(z_root() . '/embed/' . argv(1)); - } xchan_query($r); -- cgit v1.2.3 From efc4c53b44c12c98918f0c4231febb56ce785787 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 8 Feb 2019 10:15:28 +0100 Subject: missing use App --- Zotlabs/Module/Item.php | 1 + 1 file changed, 1 insertion(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 843be394f..ebcf632ef 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -12,6 +12,7 @@ use Zotlabs\Lib\LDSignatures; use Zotlabs\Zot6\HTTPSig; use Zotlabs\Lib\Libzot; use Zotlabs\Lib\ThreadListener; +use App; require_once('include/crypto.php'); require_once('include/items.php'); -- cgit v1.2.3 From f52a53277141a67b7310656a437f1dd1ef8091f1 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 8 Feb 2019 11:33:01 +0100 Subject: use ACTIVITY_SHARE to match the verb --- Zotlabs/Lib/Libzot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php index 189526c7b..019237568 100644 --- a/Zotlabs/Lib/Libzot.php +++ b/Zotlabs/Lib/Libzot.php @@ -1504,7 +1504,7 @@ class Libzot { // doesn't exist. if ($perm === 'send_stream') { - if (get_pconfig($channel['channel_id'],'system','hyperdrive',false) || $arr['verb'] === 'Announce') { + if (get_pconfig($channel['channel_id'],'system','hyperdrive',false) || $arr['verb'] === ACTIVITY_SHARE) { $allowed = true; } } -- cgit v1.2.3 From cbf6d53e8464d91eeef89b884398a15da9d72e8f Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Mon, 11 Feb 2019 20:24:17 -0500 Subject: Get all listeners --- Zotlabs/Lib/ThreadListener.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadListener.php b/Zotlabs/Lib/ThreadListener.php index ad682aac8..308e02255 100644 --- a/Zotlabs/Lib/ThreadListener.php +++ b/Zotlabs/Lib/ThreadListener.php @@ -28,7 +28,7 @@ class ThreadListener { } static public function fetch_by_target($target_id,$ltype = 0) { - $x = q("select * from listeners where target_id = '%s' and ltype = %d limit 1", + $x = q("select * from listeners where target_id = '%s' and ltype = %d", dbesc($target_id), intval($ltype) ); @@ -50,4 +50,4 @@ class ThreadListener { ); } -} \ No newline at end of file +} -- cgit v1.2.3 From 5b3ea012ab0712cd6f02fe9cb07e75f2c4b5954a Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Tue, 12 Feb 2019 22:05:57 -0500 Subject: Fix: only first lock red with privacy_warning --- Zotlabs/Lib/ThreadItem.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index bdbfc4385..323f84acf 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -76,7 +76,7 @@ class ThreadItem { * _ false on failure */ - public function get_template_data($conv_responses, $thread_level=1) { + public function get_template_data($conv_responses, $thread_level=1, $conv_flags = []) { $result = array(); @@ -117,11 +117,17 @@ class ThreadItem { } if ($lock) { - if (count(get_terms_oftype($item['term'],TERM_FORUM))) { + if (($item['mid'] == $item['parent_mid']) && count(get_terms_oftype($item['term'],TERM_FORUM))) { $privacy_warning = true; } } + if ($privacy_warning) { + $conv_flags['privacy_warning'] = $privacy_warning; + } else { + $privacy_warning = (isset($conv_flags['privacy_warning'])) ? $conv_flags['privacy_warning'] : false; + } + if ($lock && $privacy_warning) { $lock = t('Privacy conflict. Discretion advised.'); } @@ -488,7 +494,7 @@ class ThreadItem { if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) { foreach($children as $child) { - $result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1); + $result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1,$conv_flags); } // Collapse if(($nb_children > $visible_comments) || ($thread_level > 1)) { -- cgit v1.2.3 From c3e2b463e4604d5bb148ebbaa97b68ca33ce89e1 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Wed, 13 Feb 2019 08:26:03 -0500 Subject: Only cascade privacy warning if thread parent has privacy concerns. --- Zotlabs/Lib/ThreadItem.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 323f84acf..04265ee5a 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -119,14 +119,11 @@ class ThreadItem { if ($lock) { if (($item['mid'] == $item['parent_mid']) && count(get_terms_oftype($item['term'],TERM_FORUM))) { $privacy_warning = true; + $conv_flags['parent_privacy_warning'] = true; } } - if ($privacy_warning) { - $conv_flags['privacy_warning'] = $privacy_warning; - } else { - $privacy_warning = (isset($conv_flags['privacy_warning'])) ? $conv_flags['privacy_warning'] : false; - } + $privacy_warning = (isset($conv_flags['parent_privacy_warning'])) ? $conv_flags['parent_privacy_warning'] : $privacy_warning; if ($lock && $privacy_warning) { $lock = t('Privacy conflict. Discretion advised.'); -- cgit v1.2.3 From fc223f59242478ea4489dad299d9e66b6b53a23a Mon Sep 17 00:00:00 2001 From: phani00 Date: Thu, 14 Feb 2019 09:56:53 +0100 Subject: affinity slider as app --- Zotlabs/Lib/Apps.php | 1 + Zotlabs/Module/Affinity.php | 69 +++++++++++++++++++++++++++++++++++++++++++++ Zotlabs/Module/Connedit.php | 2 +- Zotlabs/Module/Network.php | 8 ++++-- Zotlabs/Widget/Affinity.php | 13 ++++++--- 5 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 Zotlabs/Module/Affinity.php (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 9edd00667..56283ff76 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -320,6 +320,7 @@ class Apps { static public function translate_system_apps(&$arr) { $apps = array( 'Apps' => t('Apps'), + 'Affinity Tool' => t('Affinity Tool'), 'Articles' => t('Articles'), 'Cards' => t('Cards'), 'Admin' => t('Site Admin'), diff --git a/Zotlabs/Module/Affinity.php b/Zotlabs/Module/Affinity.php new file mode 100644 index 000000000..8c2ee7821 --- /dev/null +++ b/Zotlabs/Module/Affinity.php @@ -0,0 +1,69 @@ + 99) + $cmax = 99; + $cmin = intval($_POST['affinity_cmin']); + if($cmin < 0 || $cmin > 99) + $cmin = 0; + set_pconfig(local_channel(),'affinity','cmin',$cmin); + set_pconfig(local_channel(),'affinity','cmax',$cmax); + + info( t('Affinity Tool settings updated.') . EOL); + + } + + Libsync::build_sync_packet(); + + } + + + function get() { + + $desc = t('This app (when installed) presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship or affinity with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.'); + + $text = ''; + + if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Affinity Tool'))) { + return $text; + } + + $text .= EOL . t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.') . EOL . EOL; + + $setting_fields = $text; + + $cmax = intval(get_pconfig(local_channel(),'affinity','cmax')); + $cmax = (($cmax) ? $cmax : 99); + $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99')) + )); + $cmin = intval(get_pconfig(local_channel(),'affinity','cmin')); + $cmin = (($cmin) ? $cmin : 0); + $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( + '$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0')) + )); + + $s .= replace_macros(get_markup_template('generic_app_settings.tpl'), array( + '$addon' => array('affinity', '' . t('Affinity Tool Settings'), '', t('Submit')), + '$content' => $setting_fields + )); + + return $s; + } + + +} diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index c14bcd0dd..a587324df 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -710,7 +710,7 @@ class Connedit extends \Zotlabs\Web\Controller { $tpl = get_markup_template("abook_edit.tpl"); - if(feature_enabled(local_channel(),'affinity')) { + if(Apps::system_app_installed(local_channel(),'Affinity Tool')) { $sections['affinity'] = [ 'label' => t('Affinity'), diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index d5cc06d09..2019082ed 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -1,6 +1,8 @@ '<' . $r[0]['hash'] . '>'); } - $default_cmin = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1)); - $default_cmax = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1)); + $default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1)); + $default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1)); $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0); $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0); @@ -132,7 +134,7 @@ class Network extends \Zotlabs\Web\Controller { $deftag = ''; - if (feature_enabled(local_channel(),'affinity')) { + if (Apps::system_app_installed(local_channel(),'Affinity Tool')) { $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); if ($affinity_locked) { set_pconfig(local_channel(),'affinity','cmin',$cmin); diff --git a/Zotlabs/Widget/Affinity.php b/Zotlabs/Widget/Affinity.php index 28190e187..140d8f8ca 100644 --- a/Zotlabs/Widget/Affinity.php +++ b/Zotlabs/Widget/Affinity.php @@ -2,20 +2,25 @@ namespace Zotlabs\Widget; +use Zotlabs\Lib\Apps; + class Affinity { function widget($arr) { if(! local_channel()) return ''; - - $default_cmin = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmin',0) : 0); - $default_cmax = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmax',99) : 99); + +// replace feature_enabled(local_channel() with +// Apps::system_app_installed(local_channel() + + $default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : 0); + $default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : 99); $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $default_cmin); $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $default_cmax); - if(feature_enabled(local_channel(),'affinity')) { + if(Apps::system_app_installed(local_channel(),'Affinity Tool')) { $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); if ($affinity_locked) { -- cgit v1.2.3 From 5ab917f606aa8221b50e39b9ff0b5182d271fe51 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 14 Feb 2019 11:06:52 +0100 Subject: affinity tool fixes --- Zotlabs/Module/Affinity.php | 84 +++++++++++++++++++++++------------- Zotlabs/Module/Settings/Featured.php | 42 ------------------ Zotlabs/Widget/Affinity.php | 78 ++++++++++++++++----------------- 3 files changed, 93 insertions(+), 111 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Affinity.php b/Zotlabs/Module/Affinity.php index 8c2ee7821..fbcb178e9 100644 --- a/Zotlabs/Module/Affinity.php +++ b/Zotlabs/Module/Affinity.php @@ -9,24 +9,30 @@ class Affinity extends \Zotlabs\Web\Controller { function post() { - if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Affinity Tool'))) { - return; - } - - if($_POST['affinity-submit']) { - $cmax = intval($_POST['affinity_cmax']); - if($cmax < 0 || $cmax > 99) - $cmax = 99; - $cmin = intval($_POST['affinity_cmin']); - if($cmin < 0 || $cmin > 99) - $cmin = 0; - set_pconfig(local_channel(),'affinity','cmin',$cmin); - set_pconfig(local_channel(),'affinity','cmax',$cmax); - - info( t('Affinity Tool settings updated.') . EOL); + if(! local_channel()) + return; + + if(! Apps::system_app_installed(local_channel(),'Affinity Tool')) + return; + + check_form_security_token_redirectOnErr('affinity', 'affinity'); + + $cmax = intval($_POST['affinity_cmax']); + if($cmax < 0 || $cmax > 99) + $cmax = 99; + + $cmin = intval($_POST['affinity_cmin']); + if($cmin < 0 || $cmin > 99) + $cmin = 0; + + $lock = intval($_POST['affinity_lock']); + + set_pconfig(local_channel(),'affinity','cmin',$cmin); + set_pconfig(local_channel(),'affinity','cmax',$cmax); + set_pconfig(local_channel(),'affinity','lock',$lock); + + info( t('Affinity Tool settings updated.') . EOL); - } - Libsync::build_sync_packet(); } @@ -34,35 +40,53 @@ class Affinity extends \Zotlabs\Web\Controller { function get() { - $desc = t('This app (when installed) presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship or affinity with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.'); + if(! local_channel()) + return; - $text = ''; + $desc = t('This app presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship (affinity) with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.'); + if(! Apps::system_app_installed(local_channel(),'Affinity Tool')) { + //Do not display any associated widgets at this point + App::$pdl = ''; - if(! ( local_channel() && Apps::system_app_installed(local_channel(),'Affinity Tool'))) { - return $text; - } + $o = '' . t('Affinity Tool App') . ' (' . t('Not Installed') . '):
'; + $o .= $desc; + return $o; + } - $text .= EOL . t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.') . EOL . EOL; + $text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.'); - $setting_fields = $text; + $content = ''; $cmax = intval(get_pconfig(local_channel(),'affinity','cmax')); $cmax = (($cmax) ? $cmax : 99); - $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( + $content .= replace_macros(get_markup_template('field_input.tpl'), array( '$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99')) )); + $cmin = intval(get_pconfig(local_channel(),'affinity','cmin')); $cmin = (($cmin) ? $cmin : 0); - $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( + $content .= replace_macros(get_markup_template('field_input.tpl'), array( '$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0')) )); - $s .= replace_macros(get_markup_template('generic_app_settings.tpl'), array( - '$addon' => array('affinity', '' . t('Affinity Tool Settings'), '', t('Submit')), - '$content' => $setting_fields + $lock = intval(get_pconfig(local_channel(),'affinity','lock',1)); + + $content .= replace_macros(get_markup_template('field_checkbox.tpl'), array( + '$field' => array('affinity_lock', t('Persistent affinity levels'), $lock, t('If disabled the max and min levels will be reset to default after page reload'), ['No','Yes']) + )); + + $tpl = get_markup_template("settings_addon.tpl"); + + $o = replace_macros($tpl, array( + '$action_url' => 'affinity', + '$form_security_token' => get_form_security_token("affinity"), + '$title' => t('Affinity Tool Settings'), + '$content' => $content, + '$baseurl' => z_root(), + '$submit' => t('Submit'), )); - return $s; + return $o; } diff --git a/Zotlabs/Module/Settings/Featured.php b/Zotlabs/Module/Settings/Featured.php index 1d903fcf7..d5d740aff 100644 --- a/Zotlabs/Module/Settings/Featured.php +++ b/Zotlabs/Module/Settings/Featured.php @@ -10,24 +10,6 @@ class Featured { call_hooks('feature_settings_post', $_POST); - if($_POST['affinity_slider-submit']) { - $cmax = intval($_POST['affinity_cmax']); - if($cmax < 0 || $cmax > 99) - $cmax = 99; - $cmin = intval($_POST['affinity_cmin']); - if($cmin < 0 || $cmin > 99) - $cmin = 0; - - $lock = ($_POST['affinity_lock']) ? intval($_POST['affinity_lock']) : 1; - - set_pconfig(local_channel(),'affinity','cmin',$cmin); - set_pconfig(local_channel(),'affinity','cmax',$cmax); - set_pconfig(local_channel(),'affinity','lock',$lock); - - info( t('Affinity Slider settings updated.') . EOL); - - } - build_sync_packet(); return; } @@ -41,34 +23,10 @@ class Featured { if(! $r) $settings_addons = t('No feature settings configured'); - if(feature_enabled(local_channel(),'affinity')) { - - $cmax = intval(get_pconfig(local_channel(),'affinity','cmax')); - $cmax = (($cmax) ? $cmax : 99); - $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( - '$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99')) - )); - $cmin = intval(get_pconfig(local_channel(),'affinity','cmin')); - $cmin = (($cmin) ? $cmin : 0); - $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( - '$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0')) - )); - $lock = intval(get_pconfig(local_channel(),'affinity','lock',1)); - $setting_fields .= replace_macros(get_markup_template('field_checkbox.tpl'), array( - '$field' => array('affinity_lock', t('Always reset on new page visit.'), $lock, t('default: yes'), Array('No','Yes')) - )); - - $settings_addons .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( - '$addon' => array('affinity_slider', '' . t('Affinity Slider Settings'), '', t('Submit')), - '$content' => $setting_fields - )); - } - call_hooks('feature_settings', $settings_addons); $this->sortpanels($settings_addons); - $tpl = get_markup_template("settings_addons.tpl"); $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("settings_featured"), diff --git a/Zotlabs/Widget/Affinity.php b/Zotlabs/Widget/Affinity.php index 140d8f8ca..572af0503 100644 --- a/Zotlabs/Widget/Affinity.php +++ b/Zotlabs/Widget/Affinity.php @@ -9,10 +9,10 @@ class Affinity { function widget($arr) { if(! local_channel()) - return ''; - -// replace feature_enabled(local_channel() with -// Apps::system_app_installed(local_channel() + return; + + if(! Apps::system_app_installed(local_channel(),'Affinity Tool')) + return; $default_cmin = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmin',0) : 0); $default_cmax = ((Apps::system_app_installed(local_channel(),'Affinity Tool')) ? get_pconfig(local_channel(),'affinity','cmax',99) : 99); @@ -20,47 +20,47 @@ class Affinity { $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $default_cmin); $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $default_cmax); - if(Apps::system_app_installed(local_channel(),'Affinity Tool')) { + $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); + if ($affinity_locked) { + set_pconfig(local_channel(),'affinity','cmin',$cmin); + set_pconfig(local_channel(),'affinity','cmax',$cmax); + } - $affinity_locked = intval(get_pconfig(local_channel(),'affinity','lock',1)); - if ($affinity_locked) { - set_pconfig(local_channel(),'affinity','cmin',$cmin); - set_pconfig(local_channel(),'affinity','cmax',$cmax); - } + $labels = array( + t('Me'), + t('Family'), + t('Friends'), + t('Acquaintances'), + t('All') + ); + call_hooks('affinity_labels',$labels); - $labels = array( - t('Me'), - t('Family'), - t('Friends'), - t('Acquaintances'), - t('All') - ); - call_hooks('affinity_labels',$labels); - $label_str = ''; + $label_str = ''; - if($labels) { - foreach($labels as $l) { - if($label_str) { - $label_str .= ", '|'"; - $label_str .= ", '" . $l . "'"; - } - else - $label_str .= "'" . $l . "'"; + if($labels) { + foreach($labels as $l) { + if($label_str) { + $label_str .= ", '|'"; + $label_str .= ", '" . $l . "'"; } + else + $label_str .= "'" . $l . "'"; } - - $tpl = get_markup_template('main_slider.tpl'); - $x = replace_macros($tpl,array( - '$val' => $cmin . ',' . $cmax, - '$refresh' => t('Refresh'), - '$labels' => $label_str, - )); - - $arr = array('html' => $x); - call_hooks('main_slider',$arr); - return $arr['html']; } - return ''; + + $tpl = get_markup_template('main_slider.tpl'); + $x = replace_macros($tpl,array( + '$val' => $cmin . ',' . $cmax, + '$refresh' => t('Refresh'), + '$labels' => $label_str, + )); + + $arr = array('html' => $x); + call_hooks('main_slider',$arr); + + return $arr['html']; + + } } -- cgit v1.2.3 From 0207b5ba8b60da0d87d32963f462254d51faddca Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 14 Feb 2019 11:32:43 +0100 Subject: disable repeats until issues are resolved --- Zotlabs/Lib/ThreadItem.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 04265ee5a..40c0fca4b 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -311,7 +311,8 @@ class ThreadItem { // This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues. // Will allow it only for uri resolvable sources. if(strpos($item['mid'],'http') === 0) { - $share = array( t('Repeat This'), t('repeat')); + $share = []; //Not yet ready for primetime + //$share = array( t('Repeat This'), t('repeat')); } $embed = array( t('Share This'), t('share')); } -- cgit v1.2.3 From 3217452b026724d5c5d72c55196d7793b3ef758a Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 14 Feb 2019 14:48:16 +0100 Subject: missing use app --- Zotlabs/Module/Affinity.php | 1 + 1 file changed, 1 insertion(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Affinity.php b/Zotlabs/Module/Affinity.php index fbcb178e9..f0d99f1e7 100644 --- a/Zotlabs/Module/Affinity.php +++ b/Zotlabs/Module/Affinity.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module; +use App; use Zotlabs\Lib\Apps; use Zotlabs\Lib\Libsync; -- cgit v1.2.3 From e6dadb215e9e08491ae57ab851960a0973d3f704 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Tue, 5 Feb 2019 23:03:03 +0100 Subject: Refactor photo_driver to use namespaces. Add simple UnitTest, but it is not yet very meaningful. --- Zotlabs/Photo/PhotoDriver.php | 468 +++++++++++++++++++++++++++++++++++++++++ Zotlabs/Photo/PhotoGd.php | 194 +++++++++++++++++ Zotlabs/Photo/PhotoImagick.php | 218 +++++++++++++++++++ 3 files changed, 880 insertions(+) create mode 100644 Zotlabs/Photo/PhotoDriver.php create mode 100644 Zotlabs/Photo/PhotoGd.php create mode 100644 Zotlabs/Photo/PhotoImagick.php (limited to 'Zotlabs') diff --git a/Zotlabs/Photo/PhotoDriver.php b/Zotlabs/Photo/PhotoDriver.php new file mode 100644 index 000000000..e2e143f8d --- /dev/null +++ b/Zotlabs/Photo/PhotoDriver.php @@ -0,0 +1,468 @@ +types = $this->supportedTypes(); + if(! array_key_exists($type, $this->types)) { + $type = 'image/jpeg'; + } + $this->type = $type; + $this->valid = false; + $this->load($data, $type); + } + + public function __destruct() { + if($this->is_valid()) + $this->destroy(); + } + + /** + * @brief Is it a valid image object. + * + * @return boolean + */ + public function is_valid() { + return $this->valid; + } + + /** + * @brief Get the width of the image. + * + * @return boolean|number Width of image in pixels, or false on failure + */ + public function getWidth() { + if(! $this->is_valid()) + return false; + + return $this->width; + } + + /** + * @brief Get the height of the image. + * + * @return boolean|number Height of image in pixels, or false on failure + */ + public function getHeight() { + if(! $this->is_valid()) + return false; + + return $this->height; + } + + /** + * @brief Saves the image resource to a file in filesystem. + * + * @param string $path Path and filename where to save the image + * @return boolean False on failure, otherwise true + */ + public function saveImage($path) { + if(! $this->is_valid()) + return false; + + return (file_put_contents($path, $this->imageString()) ? true : false); + } + + /** + * @brief Return mimetype of the image resource. + * + * @return boolean|string False on failure, otherwise mimetype. + */ + public function getType() { + if(! $this->is_valid()) + return false; + + return $this->type; + } + + /** + * @brief Return file extension of the image resource. + * + * @return boolean|string False on failure, otherwise file extension. + */ + public function getExt() { + if(! $this->is_valid()) + return false; + + return $this->types[$this->getType()]; + } + + /** + * @brief Scale image to max pixel size in either dimension. + * + * @param int $max maximum pixel size in either dimension + * @param boolean $float_height (optional) + * If true allow height to float to any length on tall images, constraining + * only the width + * @return boolean|void false on failure, otherwise void + */ + public function scaleImage($max, $float_height = true) { + if(! $this->is_valid()) + return false; + + $width = $this->width; + $height = $this->height; + + $dest_width = $dest_height = 0; + + if((! $width) || (! $height)) + return false; + + if($width > $max && $height > $max) { + + // very tall image (greater than 16:9) + // constrain the width - let the height float. + + if(((($height * 9) / 16) > $width) && ($float_height)) { + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } // else constrain both dimensions + elseif($width > $height) { + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } else { + $dest_width = intval(($width * $max) / $height); + $dest_height = $max; + } + } else { + if($width > $max) { + $dest_width = $max; + $dest_height = intval(($height * $max) / $width); + } else { + if($height > $max) { + + // very tall image (greater than 16:9) + // but width is OK - don't do anything + + if(((($height * 9) / 16) > $width) && ($float_height)) { + $dest_width = $width; + $dest_height = $height; + } else { + $dest_width = intval(($width * $max) / $height); + $dest_height = $max; + } + } else { + $dest_width = $width; + $dest_height = $height; + } + } + } + $this->doScaleImage($dest_width, $dest_height); + } + + public function scaleImageUp($min) { + if(! $this->is_valid()) { + return false; + } + + $width = $this->width; + $height = $this->height; + + $dest_width = $dest_height = 0; + + if((! $width) || (! $height)) + return false; + + if($width < $min && $height < $min) { + if($width > $height) { + $dest_width = $min; + $dest_height = intval(($height * $min) / $width); + } else { + $dest_width = intval(($width * $min) / $height); + $dest_height = $min; + } + } else { + if($width < $min) { + $dest_width = $min; + $dest_height = intval(($height * $min) / $width); + } else { + if($height < $min) { + $dest_width = intval(($width * $min) / $height); + $dest_height = $min; + } else { + $dest_width = $width; + $dest_height = $height; + } + } + } + $this->doScaleImage($dest_width, $dest_height); + } + + /** + * @brief Scales image to a square. + * + * @param int $dim Pixel of square image + * @return boolean|void false on failure, otherwise void + */ + public function scaleImageSquare($dim) { + if(! $this->is_valid()) + return false; + + $this->doScaleImage($dim, $dim); + } + + /** + * @brief Reads exif data from a given filename. + * + * @param string $filename + * @return boolean|array + */ + public function exif($filename) { + if((! function_exists('exif_read_data')) + || (! in_array($this->getType(), ['image/jpeg', 'image/tiff']))) + { + return false; + } + + /* + * PHP 7.2 allows you to use a stream resource, which should reduce/avoid + * memory exhaustion on large images. + */ + + if(version_compare(PHP_VERSION, '7.2.0') >= 0) { + $f = @fopen($filename, 'rb'); + } else { + $f = $filename; + } + + if($f) { + return @exif_read_data($f, null, true); + } + + return false; + } + + /** + * @brief Orients current image based on exif orientation information. + * + * @param array $exif + * @return boolean true if oriented, otherwise false + */ + public function orient($exif) { + if(! ($this->is_valid() && $exif)) { + return false; + } + + $ort = ((array_key_exists('IFD0', $exif)) ? $exif['IFD0']['Orientation'] : $exif['Orientation']); + + if(! $ort) { + return false; + } + + switch($ort) { + case 1 : // nothing + break; + case 2 : // horizontal flip + $this->flip(); + break; + case 3 : // 180 rotate left + $this->rotate(180); + break; + case 4 : // vertical flip + $this->flip(false, true); + break; + case 5 : // vertical flip + 90 rotate right + $this->flip(false, true); + $this->rotate(-90); + break; + case 6 : // 90 rotate right + $this->rotate(-90); + break; + case 7 : // horizontal flip + 90 rotate right + $this->flip(); + $this->rotate(-90); + break; + case 8 : // 90 rotate left + $this->rotate(90); + break; + default : + break; + } + + return true; + } + + /** + * @brief Save photo to database. + * + * @param array $arr + * @param boolean $skipcheck (optional) default false + * @return boolean|array + */ + public function save($arr, $skipcheck = false) { + if(! ($skipcheck || $this->is_valid())) { + logger('Attempt to store invalid photo.'); + return false; + } + + $p = []; + + $p['aid'] = ((intval($arr['aid'])) ? intval($arr['aid']) : 0); + $p['uid'] = ((intval($arr['uid'])) ? intval($arr['uid']) : 0); + $p['xchan'] = (($arr['xchan']) ? $arr['xchan'] : ''); + $p['resource_id'] = (($arr['resource_id']) ? $arr['resource_id'] : ''); + $p['filename'] = (($arr['filename']) ? $arr['filename'] : ''); + $p['mimetype'] = (($arr['mimetype']) ? $arr['mimetype'] : $this->getType()); + $p['album'] = (($arr['album']) ? $arr['album'] : ''); + $p['imgscale'] = ((intval($arr['imgscale'])) ? intval($arr['imgscale']) : 0); + $p['allow_cid'] = (($arr['allow_cid']) ? $arr['allow_cid'] : ''); + $p['allow_gid'] = (($arr['allow_gid']) ? $arr['allow_gid'] : ''); + $p['deny_cid'] = (($arr['deny_cid']) ? $arr['deny_cid'] : ''); + $p['deny_gid'] = (($arr['deny_gid']) ? $arr['deny_gid'] : ''); + $p['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert()); + $p['title'] = (($arr['title']) ? $arr['title'] : ''); + $p['description'] = (($arr['description']) ? $arr['description'] : ''); + $p['photo_usage'] = intval($arr['photo_usage']); + $p['os_storage'] = intval($arr['os_storage']); + $p['os_path'] = $arr['os_path']; + $p['os_syspath'] = ((array_key_exists('os_syspath', $arr)) ? $arr['os_syspath'] : ''); + $p['display_path'] = (($arr['display_path']) ? $arr['display_path'] : ''); + $p['width'] = (($arr['width']) ? $arr['width'] : $this->getWidth()); + $p['height'] = (($arr['height']) ? $arr['height'] : $this->getHeight()); + $p['expires'] = (($arr['expires']) ? $arr['expires'] : gmdate('Y-m-d H:i:s', time() + get_config('system', 'photo_cache_time', 86400))); + + if(! intval($p['imgscale'])) + logger('save: ' . print_r($arr, true), LOGGER_DATA); + + $x = q("select id, created from photo where resource_id = '%s' and uid = %d and xchan = '%s' and imgscale = %d limit 1", dbesc($p['resource_id']), intval($p['uid']), dbesc($p['xchan']), intval($p['imgscale'])); + + if($x) { + $p['created'] = (($x['created']) ? $x['created'] : $p['edited']); + $r = q("UPDATE photo set + aid = %d, + uid = %d, + xchan = '%s', + resource_id = '%s', + created = '%s', + edited = '%s', + filename = '%s', + mimetype = '%s', + album = '%s', + height = %d, + width = %d, + content = '%s', + os_storage = %d, + filesize = %d, + imgscale = %d, + photo_usage = %d, + title = '%s', + description = '%s', + os_path = '%s', + display_path = '%s', + allow_cid = '%s', + allow_gid = '%s', + deny_cid = '%s', + deny_gid = '%s', + expires = '%s' + where id = %d", + intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($x[0]['id'])); + } else { + $p['created'] = (($arr['created']) ? $arr['created'] : $p['edited']); + $r = q("INSERT INTO photo + ( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid, expires ) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )", intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires'])); + } + logger('Photo save imgscale ' . $p['imgscale'] . ' returned ' . intval($r)); + + return $r; + } + +} diff --git a/Zotlabs/Photo/PhotoGd.php b/Zotlabs/Photo/PhotoGd.php new file mode 100644 index 000000000..1143c565c --- /dev/null +++ b/Zotlabs/Photo/PhotoGd.php @@ -0,0 +1,194 @@ +valid = false; + if(! $data) + return; + + $this->image = @imagecreatefromstring($data); + if($this->image !== false) { + $this->valid = true; + $this->setDimensions(); + imagealphablending($this->image, false); + imagesavealpha($this->image, true); + } + } + + protected function setDimensions() { + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + } + + /** + * @brief GD driver does not preserve EXIF, so not need to clear it. + * + * @return void + */ + public function clearexif() { + return; + } + + protected function destroy() { + if($this->is_valid()) { + imagedestroy($this->image); + } + } + + /** + * @brief Return a PHP image resource of the current image. + * + * @see \Zotlabs\Photo\PhotoDriver::getImage() + * + * @return boolean|resource + */ + public function getImage() { + if(! $this->is_valid()) + return false; + + return $this->image; + } + + public function doScaleImage($dest_width, $dest_height) { + + $dest = imagecreatetruecolor($dest_width, $dest_height); + $width = imagesx($this->image); + $height = imagesy($this->image); + + imagealphablending($dest, false); + imagesavealpha($dest, true); + if($this->type == 'image/png') + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + + imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); + if($this->image) + imagedestroy($this->image); + + $this->image = $dest; + $this->setDimensions(); + } + + public function rotate($degrees) { + if(! $this->is_valid()) + return false; + + $this->image = imagerotate($this->image, $degrees, 0); + $this->setDimensions(); + } + + public function flip($horiz = true, $vert = false) { + if(! $this->is_valid()) + return false; + + $w = imagesx($this->image); + $h = imagesy($this->image); + $flipped = imagecreate($w, $h); + if($horiz) { + for($x = 0; $x < $w; $x++) { + imagecopy($flipped, $this->image, $x, 0, $w - $x - 1, 0, 1, $h); + } + } + if($vert) { + for($y = 0; $y < $h; $y++) { + imagecopy($flipped, $this->image, 0, $y, 0, $h - $y - 1, $w, 1); + } + } + $this->image = $flipped; + $this->setDimensions(); // Shouldn't really be necessary + } + + public function cropImage($max, $x, $y, $w, $h) { + if(!$this->is_valid()) + return false; + + $dest = imagecreatetruecolor($max, $max); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if($this->type == 'image/png') + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + + imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h); + if($this->image) + imagedestroy($this->image); + + $this->image = $dest; + $this->setDimensions(); + } + + public function cropImageRect($maxx, $maxy, $x, $y, $w, $h) { + if(! $this->is_valid()) + return false; + + $dest = imagecreatetruecolor($maxx, $maxy); + imagealphablending($dest, false); + imagesavealpha($dest, true); + if($this->type == 'image/png') + imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha + + imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $maxx, $maxy, $w, $h); + if($this->image) + imagedestroy($this->image); + + $this->image = $dest; + $this->setDimensions(); + } + + /** + * {@inheritDoc} + * @see \Zotlabs\Photo\PhotoDriver::imageString() + */ + public function imageString() { + if(! $this->is_valid()) + return false; + + $quality = false; + + ob_start(); + + switch($this->getType()){ + case 'image/png': + $quality = get_config('system', 'png_quality'); + if((! $quality) || ($quality > 9)) + $quality = PNG_QUALITY; + + \imagepng($this->image, NULL, $quality); + break; + case 'image/jpeg': + // gd can lack imagejpeg(), but we verify during installation it is available + default: + $quality = get_config('system', 'jpeg_quality'); + if((! $quality) || ($quality > 100)) + $quality = JPEG_QUALITY; + + \imagejpeg($this->image, NULL, $quality); + break; + } + $string = ob_get_contents(); + ob_end_clean(); + + return $string; + } + +} diff --git a/Zotlabs/Photo/PhotoImagick.php b/Zotlabs/Photo/PhotoImagick.php new file mode 100644 index 000000000..373bac40f --- /dev/null +++ b/Zotlabs/Photo/PhotoImagick.php @@ -0,0 +1,218 @@ + 'jpg', + 'image/png' => 'png', + 'image/gif' => 'gif', + ]; + } + + private function get_FormatsMap() { + return [ + 'image/jpeg' => 'JPG', + 'image/png' => 'PNG', + 'image/gif' => 'GIF', + ]; + } + + + protected function load($data, $type) { + $this->valid = false; + $this->image = new \Imagick(); + + if(! $data) + return; + + try { + $this->image->readImageBlob($data); + } catch(\Exception $e) { + logger('Imagick readImageBlob() exception:' . print_r($e, true)); + return; + } + + /* + * Setup the image to the format it will be saved to + */ + + $map = $this->get_FormatsMap(); + $format = $map[$type]; + + if($this->image) { + $this->image->setFormat($format); + + // Always coalesce, if it is not a multi-frame image it won't hurt anyway + $this->image = $this->image->coalesceImages(); + + $this->valid = true; + $this->setDimensions(); + + /* + * setup the compression here, so we'll do it only once + */ + switch($this->getType()) { + case 'image/png': + $quality = get_config('system', 'png_quality'); + if((! $quality) || ($quality > 9)) + $quality = PNG_QUALITY; + /* + * From http://www.imagemagick.org/script/command-line-options.php#quality: + * + * 'For the MNG and PNG image formats, the quality value sets + * the zlib compression level (quality / 10) and filter-type (quality % 10). + * The default PNG "quality" is 75, which means compression level 7 with adaptive PNG filtering, + * unless the image has a color map, in which case it means compression level 7 with no PNG filtering' + */ + $quality = $quality * 10; + $this->image->setCompressionQuality($quality); + break; + case 'image/jpeg': + $quality = get_config('system', 'jpeg_quality'); + if((! $quality) || ($quality > 100)) + $quality = JPEG_QUALITY; + $this->image->setCompressionQuality($quality); + default: + break; + } + } + } + + protected function destroy() { + if($this->is_valid()) { + $this->image->clear(); + $this->image->destroy(); + } + } + + protected function setDimensions() { + $this->width = $this->image->getImageWidth(); + $this->height = $this->image->getImageHeight(); + } + + /** + * @brief Strips the image of all profiles and comments. + * + * Keep ICC profile for better colors. + * + * @see \Zotlabs\Photo\PhotoDriver::clearexif() + */ + public function clearexif() { + $profiles = $this->image->getImageProfiles('icc', true); + + $this->image->stripImage(); + + if(! empty($profiles)) { + $this->image->profileImage('icc', $profiles['icc']); + } + } + + + /** + * @brief Return a \Imagick object of the current image. + * + * @see \Zotlabs\Photo\PhotoDriver::getImage() + * + * @return boolean|\Imagick + */ + public function getImage() { + if(! $this->is_valid()) + return false; + + $this->image = $this->image->deconstructImages(); + return $this->image; + } + + public function doScaleImage($dest_width, $dest_height) { + /* + * If it is not animated, there will be only one iteration here, + * so don't bother checking + */ + // Don't forget to go back to the first frame + $this->image->setFirstIterator(); + do { + $this->image->scaleImage($dest_width, $dest_height); + } while($this->image->nextImage()); + + $this->setDimensions(); + } + + public function rotate($degrees) { + if(! $this->is_valid()) + return false; + + $this->image->setFirstIterator(); + do { + // ImageMagick rotates in the opposite direction of imagerotate() + $this->image->rotateImage(new \ImagickPixel(), -$degrees); + } while($this->image->nextImage()); + + $this->setDimensions(); + } + + public function flip($horiz = true, $vert = false) { + if(! $this->is_valid()) + return false; + + $this->image->setFirstIterator(); + do { + if($horiz) $this->image->flipImage(); + if($vert) $this->image->flopImage(); + } while($this->image->nextImage()); + + $this->setDimensions(); // Shouldn't really be necessary + } + + public function cropImage($max,$x,$y,$w,$h) { + if(!$this->is_valid()) + return false; + + $this->image->setFirstIterator(); + do { + $this->image->cropImage($w, $h, $x, $y); + /* + * We need to remove the canvas, + * or the image is not resized to the crop: + * http://php.net/manual/en/imagick.cropimage.php#97232 + */ + $this->image->setImagePage(0, 0, 0, 0); + } while($this->image->nextImage()); + + $this->doScaleImage($max, $max); + } + + public function cropImageRect($maxx, $maxy, $x, $y, $w, $h) { + if(! $this->is_valid()) + return false; + + $this->image->setFirstIterator(); + do { + $this->image->cropImage($w, $h, $x, $y); + /* + * We need to remove the canvas, + * or the image is not resized to the crop: + * http://php.net/manual/en/imagick.cropimage.php#97232 + */ + $this->image->setImagePage(0, 0, 0, 0); + } while($this->image->nextImage()); + + $this->doScaleImage($maxx, $maxy); + } + + public function imageString() { + if(! $this->is_valid()) + return false; + + /* Clean it */ + $this->image = $this->image->deconstructImages(); + + return $this->image->getImagesBlob(); + } + +} -- cgit v1.2.3 From b9df4c99cf9fcd1b16757309b4206ad084376aa2 Mon Sep 17 00:00:00 2001 From: Klaus Weidenbach Date: Mon, 11 Feb 2019 23:59:43 +0100 Subject: Remove duplicate code in PhotoDriver classes. cropImage is just a special case of cropImageRect, no need to duplicate all the code. --- Zotlabs/Photo/PhotoDriver.php | 34 ++++++++++++++++++++++++++++++++-- Zotlabs/Photo/PhotoGd.php | 18 ------------------ Zotlabs/Photo/PhotoImagick.php | 18 ------------------ 3 files changed, 32 insertions(+), 38 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Photo/PhotoDriver.php b/Zotlabs/Photo/PhotoDriver.php index e2e143f8d..c47a7c3b2 100644 --- a/Zotlabs/Photo/PhotoDriver.php +++ b/Zotlabs/Photo/PhotoDriver.php @@ -80,8 +80,18 @@ abstract class PhotoDriver { abstract public function flip($horiz = true, $vert = false); - abstract public function cropImage($max, $x, $y, $w, $h); - + /** + * @brief Crops the image. + * + * @param int $maxx width of the new image + * @param int $maxy height of the new image + * @param int $x x-offset for region + * @param int $y y-offset for region + * @param int $w width of region + * @param int $h height of region + * + * @return boolean|void false on failure + */ abstract public function cropImageRect($maxx, $maxy, $x, $y, $w, $h); /** @@ -299,6 +309,26 @@ abstract class PhotoDriver { $this->doScaleImage($dim, $dim); } + /** + * @brief Crops a square image. + * + * @see cropImageRect() + * + * @param int $max size of the new image + * @param int $x x-offset for region + * @param int $y y-offset for region + * @param int $w width of region + * @param int $h height of region + * + * @return boolean|void false on failure + */ + public function cropImage($max, $x, $y, $w, $h) { + if(! $this->is_valid()) + return false; + + $this->cropImageRect($max, $max, $x, $y, $w, $h); + } + /** * @brief Reads exif data from a given filename. * diff --git a/Zotlabs/Photo/PhotoGd.php b/Zotlabs/Photo/PhotoGd.php index 1143c565c..4054e1866 100644 --- a/Zotlabs/Photo/PhotoGd.php +++ b/Zotlabs/Photo/PhotoGd.php @@ -119,24 +119,6 @@ class PhotoGd extends PhotoDriver { $this->setDimensions(); // Shouldn't really be necessary } - public function cropImage($max, $x, $y, $w, $h) { - if(!$this->is_valid()) - return false; - - $dest = imagecreatetruecolor($max, $max); - imagealphablending($dest, false); - imagesavealpha($dest, true); - if($this->type == 'image/png') - imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha - - imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h); - if($this->image) - imagedestroy($this->image); - - $this->image = $dest; - $this->setDimensions(); - } - public function cropImageRect($maxx, $maxy, $x, $y, $w, $h) { if(! $this->is_valid()) return false; diff --git a/Zotlabs/Photo/PhotoImagick.php b/Zotlabs/Photo/PhotoImagick.php index 373bac40f..a7026e8ca 100644 --- a/Zotlabs/Photo/PhotoImagick.php +++ b/Zotlabs/Photo/PhotoImagick.php @@ -169,24 +169,6 @@ class PhotoImagick extends PhotoDriver { $this->setDimensions(); // Shouldn't really be necessary } - public function cropImage($max,$x,$y,$w,$h) { - if(!$this->is_valid()) - return false; - - $this->image->setFirstIterator(); - do { - $this->image->cropImage($w, $h, $x, $y); - /* - * We need to remove the canvas, - * or the image is not resized to the crop: - * http://php.net/manual/en/imagick.cropimage.php#97232 - */ - $this->image->setImagePage(0, 0, 0, 0); - } while($this->image->nextImage()); - - $this->doScaleImage($max, $max); - } - public function cropImageRect($maxx, $maxy, $x, $y, $w, $h) { if(! $this->is_valid()) return false; -- cgit v1.2.3 From ca917f7b9ae3f47f7159179f34fe769fb4665e5f Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 15 Feb 2019 11:39:59 +0100 Subject: exclude addon_common from addon list --- Zotlabs/Module/Admin/Addons.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Admin/Addons.php b/Zotlabs/Module/Admin/Addons.php index b35922aef..b8e3e3a2e 100644 --- a/Zotlabs/Module/Admin/Addons.php +++ b/Zotlabs/Module/Admin/Addons.php @@ -375,6 +375,9 @@ class Addons { if($files) { foreach($files as $file) { if (is_dir($file)){ + if($file == 'addon/addon_common/') + continue; + list($tmp, $id) = array_map('trim', explode('/', $file)); $info = get_plugin_info($id); $enabled = in_array($id,\App::$plugins); @@ -476,4 +479,4 @@ class Addons { return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name']))); } -} \ No newline at end of file +} -- cgit v1.2.3 From 4769254978a55efd0e8ba6586d1497b5f29d2bd4 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 15 Feb 2019 12:35:19 +0100 Subject: deprecate addon settings --- Zotlabs/Widget/Settings_menu.php | 7 ------- 1 file changed, 7 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index c537c3835..25b80a4b4 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -42,19 +42,12 @@ class Settings_menu { ); - $tabs[] = array( 'label' => t('Display settings'), 'url' => z_root().'/settings/display', 'selected' => ((argv(1) === 'display') ? 'active' : ''), ); - $tabs[] = array( - 'label' => t('Addon settings'), - 'url' => z_root().'/settings/featured', - 'selected' => ((argv(1) === 'featured') ? 'active' : ''), - ); - if($hublocs) { $tabs[] = array( 'label' => t('Manage locations'), -- cgit v1.2.3 From b070503e773e5b9a95639b0df7e4bb515855054b Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sun, 17 Feb 2019 22:47:08 +0100 Subject: MySQL 8 admin summary compatibility --- Zotlabs/Module/Admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Admin.php b/Zotlabs/Module/Admin.php index 8ccdaf4f5..88b84b9d2 100644 --- a/Zotlabs/Module/Admin.php +++ b/Zotlabs/Module/Admin.php @@ -86,7 +86,7 @@ class Admin extends \Zotlabs\Web\Controller { // list total user accounts, expirations etc. $accounts = array(); - $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account", + $r = q("SELECT COUNT(CASE WHEN account_id > 0 THEN 1 ELSE NULL END) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account", db_utcnow(), db_utcnow(), dbesc(NULL_DATE), -- cgit v1.2.3 From 13ca56d38041c9da499bba54c1ebbaf98baa68cd Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 18 Feb 2019 14:27:01 +0100 Subject: if local_channel() and updating the page do not query for another item if the first query returned no results. we will most probably find an item from another channel (e.g. after liking a comment) and end up with multiple items with the same mid from different channels after the page update --- Zotlabs/Module/Display.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index e3691702d..04e5f9fce 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -178,8 +178,7 @@ class Display extends \Zotlabs\Web\Controller { $static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0); - - + $simple_update = (($update) ? " AND item_unseen = 1 " : ''); if($update && $_SESSION['loadtime']) @@ -314,7 +313,7 @@ class Display extends \Zotlabs\Web\Controller { } } - if(! $r) { + if($r === null) { // in case somebody turned off public access to sys channel content using permissions // make that content unsearchable by ensuring the owner_xchan can't match if(! perm_is_allowed($sysid,$observer_hash,'view_stream')) -- cgit v1.2.3