From d71e70bedf4fa7244f3fcce789e29504c452d5cd Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 12 Jul 2018 16:23:32 -0700 Subject: functions to support module and widget registration by plugins. These have identical construction to core modules and widgets and are registered just like hooks during addon load. Also additional Apps functions addon_app_installed() and system_app_installed() which will eventually replace feature_installed() for features which are converted to apps. The convention being used is that the module associated with the app calls the appropriate *_app_installed() function and if not present emits descriptive text about the app and exits. This allows one to click on an 'available' app and learn about it. Once installed, the app module behaves normally and may offer functionality or what once were addon settings on the settings/featured page. Refer to zap-addons in the zap repository for examples of how this is being used to eliminate the 'additional features' and 'addon settings' pages. --- Zotlabs/Extend/Route.php | 48 +++++++++++++++++++++++++++++++++++++++++++++ Zotlabs/Extend/Widget.php | 47 ++++++++++++++++++++++++++++++++++++++++++++ Zotlabs/Lib/Apps.php | 36 ++++++++++++++++++++++++++++------ Zotlabs/Render/Comanche.php | 34 ++++++++++++++++++++++---------- Zotlabs/Web/Router.php | 32 +++++++++++++++++++++++------- 5 files changed, 174 insertions(+), 23 deletions(-) create mode 100644 Zotlabs/Extend/Route.php create mode 100644 Zotlabs/Extend/Widget.php (limited to 'Zotlabs') diff --git a/Zotlabs/Extend/Route.php b/Zotlabs/Extend/Route.php new file mode 100644 index 000000000..f7b90ec6e --- /dev/null +++ b/Zotlabs/Extend/Route.php @@ -0,0 +1,48 @@ + $x)); + // we don't sync system apps - they may be completely different on the other system + build_sync_packet($uid,array('app' => $x)); + } } else { self::app_undestroy($uid,$app); @@ -605,6 +607,28 @@ class Apps { } + static public function addon_app_installed($uid,$app) { + + $r = q("select id from app where app_plugin = '%s' and app_channel = %d limit 1", + dbesc($app), + intval($uid) + ); + return(($r) ? true : false); + + } + + static public function system_app_installed($uid,$app) { + + $r = q("select id from app where app_id = '%s' and app_channel = %d limit 1", + dbesc(hash('whirlpool',$app)), + intval($uid) + ); + return(($r) ? true : false); + + } + + + static public function app_list($uid, $deleted = false, $cats = []) { if($deleted) $sql_extra = ""; diff --git a/Zotlabs/Render/Comanche.php b/Zotlabs/Render/Comanche.php index fb400b6fe..f58dba60e 100644 --- a/Zotlabs/Render/Comanche.php +++ b/Zotlabs/Render/Comanche.php @@ -528,18 +528,32 @@ class Comanche { $clsname = ucfirst($name); $nsname = "\\Zotlabs\\Widget\\" . $clsname; - if(file_exists('Zotlabs/SiteWidget/' . $clsname . '.php')) - require_once('Zotlabs/SiteWidget/' . $clsname . '.php'); - elseif(file_exists('widget/' . $clsname . '/' . $clsname . '.php')) - require_once('widget/' . $clsname . '/' . $clsname . '.php'); - elseif(file_exists('Zotlabs/Widget/' . $clsname . '.php')) - require_once('Zotlabs/Widget/' . $clsname . '.php'); - else { - $pth = theme_include($clsname . '.php'); - if($pth) { - require_once($pth); + $found = false; + $widgets = \Zotlabs\Extend\Widget::get(); + if($widgets) { + foreach($widgets as $widget) { + if(is_array($widget) && strtolower($widget[1]) === strtolower($name) && file_exists($widget[0])) { + require_once($widget[0]); + $found = true; + } } } + + if(! $found) { + if(file_exists('Zotlabs/SiteWidget/' . $clsname . '.php')) + require_once('Zotlabs/SiteWidget/' . $clsname . '.php'); + elseif(file_exists('widget/' . $clsname . '/' . $clsname . '.php')) + require_once('widget/' . $clsname . '/' . $clsname . '.php'); + elseif(file_exists('Zotlabs/Widget/' . $clsname . '.php')) + require_once('Zotlabs/Widget/' . $clsname . '.php'); + else { + $pth = theme_include($clsname . '.php'); + if($pth) { + require_once($pth); + } + } + } + if(class_exists($nsname)) { $x = new $nsname; $f = 'widget'; diff --git a/Zotlabs/Web/Router.php b/Zotlabs/Web/Router.php index fb551e36f..c4db0ef3e 100644 --- a/Zotlabs/Web/Router.php +++ b/Zotlabs/Web/Router.php @@ -2,6 +2,7 @@ namespace Zotlabs\Web; +use Zotlabs\Extend\Route; use Exception; /** @@ -52,14 +53,31 @@ class Router { * First see if we have a plugin which is masquerading as a module. */ - if(is_array(\App::$plugins) && in_array($module,\App::$plugins) && file_exists("addon/{$module}/{$module}.php")) { - include_once("addon/{$module}/{$module}.php"); - if(class_exists($modname)) { - $this->controller = new $modname; - \App::$module_loaded = true; + $routes = Route::get(); + if($routes) { + foreach($routes as $route) { + if(is_array($route) && strtolower($route[1]) === $module) { + include_once($route[0]); + if(class_exists($modname)) { + $this->controller = new $modname; + \App::$module_loaded = true; + } + } } - elseif(function_exists($module . '_module')) { - \App::$module_loaded = true; + } + + // legacy plugins - this can be removed when they have all been converted + + if(! (\App::$module_loaded)) { + if(is_array(\App::$plugins) && in_array($module,\App::$plugins) && file_exists("addon/{$module}/{$module}.php")) { + include_once("addon/{$module}/{$module}.php"); + if(class_exists($modname)) { + $this->controller = new $modname; + \App::$module_loaded = true; + } + elseif(function_exists($module . '_module')) { + \App::$module_loaded = true; + } } } -- cgit v1.2.3 From 82a4bbd571131462bbff1cb2455af46747f3b840 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 15 Jul 2018 23:32:09 -0700 Subject: spellcheck --- Zotlabs/Module/Settings/Oauth2.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Oauth2.php b/Zotlabs/Module/Settings/Oauth2.php index 985095115..f58d01d8c 100644 --- a/Zotlabs/Module/Settings/Oauth2.php +++ b/Zotlabs/Module/Settings/Oauth2.php @@ -115,8 +115,8 @@ class Oauth2 { '$name' => array('name', t('Name'), $app['client_id'], t('Name of application')), '$secret' => array('secret', t('Consumer Secret'), $app['client_secret'], t('Automatically generated - change if desired. Max length 20')), '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], t('Redirect URI - leave blank unless your application specifically requires this')), - '$grant' => array('grant', t('Grant Types'), $app['grant_types'], t('leave blank unless your application sepcifically requires this')), - '$scope' => array('scope', t('Authorization scope'), $app['scope'], t('leave blank unless your application sepcifically requires this')), + '$grant' => array('grant', t('Grant Types'), $app['grant_types'], t('leave blank unless your application specifically requires this')), + '$scope' => array('scope', t('Authorization scope'), $app['scope'], t('leave blank unless your application specifically requires this')), )); return $o; } -- cgit v1.2.3 From 5ce50d0a2e15ae66765a68ba2785a87ecda57f6a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 18 Jul 2018 17:05:38 -0700 Subject: mangled urls on redirects --- Zotlabs/Module/Magic.php | 7 ++++--- Zotlabs/Module/Manage.php | 2 +- Zotlabs/Module/Nojs.php | 4 ++-- Zotlabs/Module/Rmagic.php | 10 +++++----- Zotlabs/Web/CheckJS.php | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php index 25c318f30..e034f1cdf 100644 --- a/Zotlabs/Module/Magic.php +++ b/Zotlabs/Module/Magic.php @@ -14,15 +14,16 @@ class Magic extends \Zotlabs\Web\Controller { logger('mod_magic: args: ' . print_r($_REQUEST,true),LOGGER_DATA); $addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : ''); + $bdest = ((x($_REQUEST,'bdest')) ? $_REQUEST['bdest'] : ''); $dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : ''); $test = ((x($_REQUEST,'test')) ? intval($_REQUEST['test']) : 0); $rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0); $owa = ((x($_REQUEST,'owa')) ? intval($_REQUEST['owa']) : 0); $delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : ''); - // Apache(?) appears to perform an htmlentities() operation on this variable - - $dest = html_entity_decode($dest); + + if($bdest) + $dest = hex2bin($bdest); $parsed = parse_url($dest); if(! $parsed) { diff --git a/Zotlabs/Module/Manage.php b/Zotlabs/Module/Manage.php index 9c5c32294..2c88a4df0 100644 --- a/Zotlabs/Module/Manage.php +++ b/Zotlabs/Module/Manage.php @@ -156,7 +156,7 @@ class Manage extends \Zotlabs\Web\Controller { if($delegates) { for($x = 0; $x < count($delegates); $x ++) { - $delegates[$x]['link'] = 'magic?f=&dest=' . urlencode($delegates[$x]['xchan_url']) + $delegates[$x]['link'] = 'magic?f=&bdest=' . bin2hex($delegates[$x]['xchan_url']) . '&delegate=' . urlencode($delegates[$x]['xchan_addr']); $delegates[$x]['channel_name'] = $delegates[$x]['xchan_name']; $delegates[$x]['delegate'] = 1; diff --git a/Zotlabs/Module/Nojs.php b/Zotlabs/Module/Nojs.php index 6fd6d8106..5f3d80ecd 100644 --- a/Zotlabs/Module/Nojs.php +++ b/Zotlabs/Module/Nojs.php @@ -7,8 +7,8 @@ class Nojs extends \Zotlabs\Web\Controller { function init() { $n = ((argc() > 1) ? intval(argv(1)) : 1); setcookie('jsdisabled', $n, 0, '/'); - $p = $_GET['redir']; - $hasq = strpos($p,'?'); + $p = hex2bin($_GET['redir']); + $hasq = strpbrk($p,'?&'); goaway(z_root() . (($p) ? '/' . $p : '') . (($hasq) ? '' : '?f=' ) . '&jsdisabled=' . $n); } diff --git a/Zotlabs/Module/Rmagic.php b/Zotlabs/Module/Rmagic.php index bfc03f6ec..33a6689ca 100644 --- a/Zotlabs/Module/Rmagic.php +++ b/Zotlabs/Module/Rmagic.php @@ -17,8 +17,8 @@ class Rmagic extends \Zotlabs\Web\Controller { if($r) { if($r[0]['hubloc_url'] === z_root()) goaway(z_root() . '/login'); - $dest = z_root() . '/' . str_replace(['rmagic','zid='],['','zid_='],\App::$query_string); - goaway($r[0]['hubloc_url'] . '/magic' . '?f=&owa=1&dest=' . $dest); + $dest = bin2hex(z_root() . '/' . str_replace(['rmagic','zid='],['','zid_='],\App::$query_string)); + goaway($r[0]['hubloc_url'] . '/magic' . '?f=&owa=1&bdest=' . $dest); } } } @@ -59,11 +59,11 @@ class Rmagic extends \Zotlabs\Web\Controller { if($url) { if($_SESSION['return_url']) - $dest = urlencode(z_root() . '/' . str_replace('zid=','zid_=',$_SESSION['return_url'])); + $dest = bin2hex(z_root() . '/' . str_replace('zid=','zid_=',$_SESSION['return_url'])); else - $dest = urlencode(z_root() . '/' . str_replace([ 'rmagic', 'zid=' ] ,[ '', 'zid_='],\App::$query_string)); + $dest = bin2hex(z_root() . '/' . str_replace([ 'rmagic', 'zid=' ] ,[ '', 'zid_='],\App::$query_string)); - goaway($url . '/magic' . '?f=&owa=1&dest=' . $dest); + goaway($url . '/magic' . '?f=&owa=1&bdest=' . $dest); } } } diff --git a/Zotlabs/Web/CheckJS.php b/Zotlabs/Web/CheckJS.php index 8179ceb15..c8547b6dd 100644 --- a/Zotlabs/Web/CheckJS.php +++ b/Zotlabs/Web/CheckJS.php @@ -18,7 +18,7 @@ class CheckJS { $this->jsdisabled = 0; if(! $this->jsdisabled) { - $page = urlencode(\App::$query_string); + $page = bin2hex(\App::$query_string); if($test) { $this->jsdisabled = 1; -- cgit v1.2.3 From a05c8ff66bd8d09f69f6c59bc49b7627792f4109 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 18 Jul 2018 17:48:23 -0700 Subject: query filter was a bit greedy --- Zotlabs/Module/Magic.php | 1 - 1 file changed, 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php index e034f1cdf..be6866592 100644 --- a/Zotlabs/Module/Magic.php +++ b/Zotlabs/Module/Magic.php @@ -21,7 +21,6 @@ class Magic extends \Zotlabs\Web\Controller { $owa = ((x($_REQUEST,'owa')) ? intval($_REQUEST['owa']) : 0); $delegate = ((x($_REQUEST,'delegate')) ? $_REQUEST['delegate'] : ''); - if($bdest) $dest = hex2bin($bdest); -- cgit v1.2.3 From a94c9d270906136f69156c0e7c0bd2c8a2e63d1a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 19 Jul 2018 17:19:19 -0700 Subject: checkjs fix ($page not bin-hex in all cases) --- Zotlabs/Web/CheckJS.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/CheckJS.php b/Zotlabs/Web/CheckJS.php index c8547b6dd..e83ccf27b 100644 --- a/Zotlabs/Web/CheckJS.php +++ b/Zotlabs/Web/CheckJS.php @@ -17,9 +17,9 @@ class CheckJS { else $this->jsdisabled = 0; - if(! $this->jsdisabled) { - $page = bin2hex(\App::$query_string); + $page = bin2hex(\App::$query_string); + if(! $this->jsdisabled) { if($test) { $this->jsdisabled = 1; if(array_key_exists('jsdisabled',$_COOKIE)) -- cgit v1.2.3 From b0c8e75c6e1621470e360f42eff1454241e41e8b Mon Sep 17 00:00:00 2001 From: kostikov Date: Wed, 25 Jul 2018 22:28:21 +0200 Subject: Fix duplicate transport displaying --- Zotlabs/Module/Siteinfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Siteinfo.php b/Zotlabs/Module/Siteinfo.php index 25276815d..79b94662d 100644 --- a/Zotlabs/Module/Siteinfo.php +++ b/Zotlabs/Module/Siteinfo.php @@ -32,7 +32,7 @@ class Siteinfo extends \Zotlabs\Web\Controller { '$transport_link' => 'https://zotlabs.com', '$additional_text' => t('Additional federated transport protocols:'), - '$additional_fed' => implode(',',$federated), + '$additional_fed' => implode(', ',array_unique($federated)), '$prj_version' => ((get_config('system','hidden_version_siteinfo')) ? '' : sprintf( t('Version %s'), \Zotlabs\Lib\System::get_project_version())), '$prj_linktxt' => t('Project homepage'), '$prj_srctxt' => t('Developer homepage'), -- cgit v1.2.3 From 0fe7004d38f884ddde310a7dd2aca87b8154f15b Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 27 Jul 2018 11:03:02 +0200 Subject: Update Apps.php --- Zotlabs/Lib/Apps.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 82f0b57b8..d89d8b878 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -323,7 +323,10 @@ class Apps { 'Features' => t('Features'), 'Language' => t('Language'), 'Post' => t('Post'), - 'Profile Photo' => t('Profile Photo') + 'Profile Photo' => t('Profile Photo'), + 'Profile' => t('Profile'), + 'Profiles' => t('Profiles'), + 'Privacy Groups' => t('Privacy Groups') ); if(array_key_exists('name',$arr)) { -- cgit v1.2.3 From 4fd9d1ee5ff95822975bb530fa42c31f48caeff3 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 27 Jul 2018 11:29:38 +0200 Subject: Update Apps.php --- Zotlabs/Lib/Apps.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index d89d8b878..abac2090e 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -324,9 +324,10 @@ class Apps { 'Language' => t('Language'), 'Post' => t('Post'), 'Profile Photo' => t('Profile Photo'), - 'Profile' => t('Profile'), - 'Profiles' => t('Profiles'), - 'Privacy Groups' => t('Privacy Groups') + 'Profile' => t('Profile'), + 'Profiles' => t('Profiles'), + 'Privacy Groups' => t('Privacy Groups'), + 'Notifications' => t('Notifications') ); if(array_key_exists('name',$arr)) { -- cgit v1.2.3 From e28dab17d6b958d6ef76181d23f784d17bc70b5e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 27 Jul 2018 13:59:27 -0700 Subject: app update and ownership issues --- Zotlabs/Lib/Apps.php | 57 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 7 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 82f0b57b8..b337a3bcd 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -140,10 +140,15 @@ class Apps { foreach(self::$available_apps as $iapp) { if($iapp['app_id'] == hash('whirlpool',$app['name'])) { $notfound = false; - if(($iapp['app_version'] != $app['version']) + if(($iapp['app_version'] !== $app['version']) || ($app['plugin'] && (! $iapp['app_plugin']))) { return intval($iapp['app_id']); } + + if(($iapp['app_url'] !== $app['url']) + || ($iapp['app_photo'] !== $app['photo'])) { + return intval($iapp['app_id']); + } } } @@ -198,12 +203,11 @@ class Apps { if($lines) { foreach($lines as $x) { if(preg_match('/^([a-zA-Z].*?):(.*?)$/ism',$x,$matches)) { - $ret[$matches[1]] = trim(str_replace(array('$baseurl','$nick'),array($baseurl,$address),$matches[2])); + $ret[$matches[1]] = trim($matches[2]); } } } - if(! $ret['photo']) $ret['photo'] = $baseurl . '/' . get_default_profile_photo(80); @@ -372,9 +376,24 @@ class Apps { $papp['papp'] = self::papp_encode($papp); + // This will catch somebody clicking on a system "available" app that hasn't had the path macros replaced + // and they are allowed to see the app + + + if(strstr($papp['url'],'$baseurl') || strstr($papp['url'],'$nick') || strstr($papp['photo'],'$baseurl') || strstr($pap['photo'],'$nick')) { + $view_channel = local_channel(); + if(! $view_channel) { + $sys = get_sys_channel(); + $view_channel = $sys['channel_id']; + } + self::app_macros($view_channel,$papp); + } + if(! strstr($papp['url'],'://')) $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)) { @@ -811,6 +830,29 @@ class Apps { } + static public function app_macros($uid,&$arr) { + + if(! intval($uid)) + return; + + $baseurl = z_root(); + $channel = channelx_by_n($uid); + $address = (($channel) ? $channel['channel_address'] : ''); + + //future expansion + + $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)); @@ -820,6 +862,7 @@ class Apps { $sys = get_sys_channel(); + self::app_macros($arr['uid'],$arr); $darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : ''); $darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0); @@ -905,11 +948,14 @@ class Apps { $darray = array(); $ret = array('success' => false); + self::app_macros($arr['uid'],$arr); + + $darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : ''); $darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0); $darray['app_id'] = ((x($arr,'guid')) ? $arr['guid'] : 0); - if((! $darray['app_url']) || (! $darray['app_channel']) || (! $darray['app_id'])) + if((! $darray['app_url']) || (! $darray['app_id'])) return $ret; if($arr['photo'] && (strpos($arr['photo'],'icon:') !== 0) && (! strstr($arr['photo'],z_root()))) { @@ -996,9 +1042,6 @@ class Apps { $ret['type'] = 'personal'; - if($app['app_id']) - $ret['guid'] = $app['app_id']; - if($app['app_id']) $ret['guid'] = $app['app_id']; -- cgit v1.2.3 From e25d205a7f1428588edd431002a2e10833c8f76e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 27 Jul 2018 14:36:06 -0700 Subject: app delete issue with base installed apps and app photo being reloaded uneccessarily --- Zotlabs/Lib/Apps.php | 66 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 19 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index b337a3bcd..841fffd39 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -56,12 +56,8 @@ class Apps { } - - static public function import_system_apps() { - if(! local_channel()) - return; - - self::$base_apps = get_config('system','base_apps',[ + static public function get_base_apps() { + return get_config('system','base_apps',[ 'Connections', 'Suggest Channels', 'Grid', @@ -77,7 +73,16 @@ class Apps { 'Mail', 'Profile Photo' ]); + } + + + static public function import_system_apps() { + if(! local_channel()) + return; + + self::$base_apps = self::get_base_apps(); + $apps = self::get_system_apps(false); self::$available_apps = q("select * from app where app_channel = 0"); @@ -537,9 +542,26 @@ class Apps { return false; } - static public function app_destroy($uid,$app) { + + static public function can_delete($uid,$app) { + if(! $uid) { + return false; + } + + $base_apps = self::get_base_apps(); + if($base_apps) { + foreach($base_apps as $b) { + if($app['guid'] === hash('whirlpool',$b)) { + return false; + } + } + } + return true; + } + 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", @@ -549,25 +571,31 @@ class Apps { if($x) { if(! intval($x[0]['app_deleted'])) { $x[0]['app_deleted'] = 1; - q("delete from term where otype = %d and oid = %d", - intval(TERM_OBJ_APP), - intval($x[0]['id']) - ); - if ($uid) { + if(self::can_delete($uid,$app)) { $r = q("delete from app where app_id = '%s' and app_channel = %d", dbesc($app['guid']), intval($uid) ); - - // we don't sync system apps - they may be completely different on the other system - build_sync_packet($uid,array('app' => $x)); + q("delete from term where otype = %d and oid = %d", + intval(TERM_OBJ_APP), + intval($x[0]['id']) + ); + } + else { + $r = q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d", + dbesc($app['guid']), + intval($uid) + ); } + + build_sync_packet($uid,array('app' => $x)); } else { self::app_undestroy($uid,$app); } } } + } static public function app_undestroy($uid,$app) { @@ -874,8 +902,8 @@ class Apps { $arr['author'] = $sys['channel_hash']; } - if($arr['photo'] && (strpos($arr['photo'],'icon:') !== 0) && (! strstr($arr['photo'],z_root()))) { - $x = import_xchan_photo($arr['photo'],get_observer_hash(),true); + if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (! strstr($arr['photo'],z_root()))) { + $x = import_xchan_photo(str_replace('$baseurl',z_root(),$arr['photo']),get_observer_hash(),true); $arr['photo'] = $x[1]; } @@ -958,8 +986,8 @@ class Apps { if((! $darray['app_url']) || (! $darray['app_id'])) return $ret; - if($arr['photo'] && (strpos($arr['photo'],'icon:') !== 0) && (! strstr($arr['photo'],z_root()))) { - $x = import_xchan_photo($arr['photo'],get_observer_hash(),true); + if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (! strstr($arr['photo'],z_root()))) { + $x = import_xchan_photo(str_replace('$baseurl',z_root(),$arr['photo']),get_observer_hash(),true); $arr['photo'] = $x[1]; } -- cgit v1.2.3 From a0f28708ab125e953157299d13d8ebbea8b77396 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 27 Jul 2018 15:05:29 -0700 Subject: don't sync system apps --- Zotlabs/Lib/Apps.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 841fffd39..ddaf8c44d 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -527,7 +527,7 @@ class Apps { intval($uid) ); if($r) { - if(! $r[0]['app_system']) { + if(($app['uid']) && (! $r[0]['app_system'])) { if($app['categories'] && (! $app['term'])) { $r[0]['term'] = q("select * from term where otype = %d and oid = %d", intval(TERM_OBJ_APP), @@ -587,8 +587,9 @@ class Apps { intval($uid) ); } - - build_sync_packet($uid,array('app' => $x)); + if(! intval($x[0]['app_system'])) { + build_sync_packet($uid,array('app' => $x)); + } } else { self::app_undestroy($uid,$app); -- cgit v1.2.3 From 97015162282989913d6b54c373af3b73b8043bad Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sat, 28 Jul 2018 17:17:12 -0700 Subject: fix unsanitised xchan_name --- Zotlabs/Update/_1216.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Zotlabs/Update/_1216.php (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1216.php b/Zotlabs/Update/_1216.php new file mode 100644 index 000000000..843567633 --- /dev/null +++ b/Zotlabs/Update/_1216.php @@ -0,0 +1,19 @@ + Date: Sun, 29 Jul 2018 06:58:35 +0200 Subject: wrong class name --- Zotlabs/Update/_1216.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1216.php b/Zotlabs/Update/_1216.php index 843567633..8890795f1 100644 --- a/Zotlabs/Update/_1216.php +++ b/Zotlabs/Update/_1216.php @@ -2,7 +2,7 @@ namespace Zotlabs\Update; -class _1215 { +class _1216 { function run() { -- cgit v1.2.3 From e4a1286aae411023210628d3be306420f7844d22 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sun, 29 Jul 2018 08:05:41 +0200 Subject: fix sql empty query error in db update 1216 --- Zotlabs/Update/_1216.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1216.php b/Zotlabs/Update/_1216.php index 8890795f1..69f2be15a 100644 --- a/Zotlabs/Update/_1216.php +++ b/Zotlabs/Update/_1216.php @@ -6,7 +6,7 @@ class _1216 { function run() { - $r = q("UPDATE xchan set xchan_name = 'unknown' where xchan_name like '%<%' "); + $r = dbq("UPDATE xchan set xchan_name = 'unknown' where xchan_name like '%<%' "); if($r) { return UPDATE_SUCCESS; -- cgit v1.2.3 From e8aeecc4c9842d4c6b25f7b488ede9644afc5d78 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 30 Jul 2018 17:41:37 -0700 Subject: When checking permissions ignore checking site "Block Public" settings in cases where site permissions aren't applicable --- Zotlabs/Module/Connedit.php | 2 +- Zotlabs/Module/Defperms.php | 1 - Zotlabs/Module/Settings/Tokens.php | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index cb9c19cf0..712215bc3 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -774,7 +774,7 @@ class Connedit extends \Zotlabs\Web\Controller { $global_perms = \Zotlabs\Access\Permissions::Perms(); - $existing = get_all_perms(local_channel(),$contact['abook_xchan']); + $existing = get_all_perms(local_channel(),$contact['abook_xchan'],false); $unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes'))); diff --git a/Zotlabs/Module/Defperms.php b/Zotlabs/Module/Defperms.php index 97d9cfd1d..63acc9795 100644 --- a/Zotlabs/Module/Defperms.php +++ b/Zotlabs/Module/Defperms.php @@ -209,7 +209,6 @@ class Defperms extends \Zotlabs\Web\Controller { $global_perms = \Zotlabs\Access\Permissions::Perms(); - $existing = get_all_perms(local_channel(),$contact['abook_xchan']); $hidden_perms = []; foreach($global_perms as $k => $v) { diff --git a/Zotlabs/Module/Settings/Tokens.php b/Zotlabs/Module/Settings/Tokens.php index 619c8b5ba..e59cf8d1c 100644 --- a/Zotlabs/Module/Settings/Tokens.php +++ b/Zotlabs/Module/Settings/Tokens.php @@ -117,7 +117,7 @@ class Tokens { $global_perms = \Zotlabs\Access\Permissions::Perms(); $their_perms = []; - $existing = get_all_perms(local_channel(),(($atoken_xchan) ? $atoken_xchan : '')); + $existing = get_all_perms(local_channel(),(($atoken_xchan) ? $atoken_xchan : ''),false); if($atoken_xchan) { $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", -- cgit v1.2.3 From 4d0611b7d4be21d9b436348fbe9b7b1a4c0b189c Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 1 Aug 2018 16:12:44 -0700 Subject: hubzilla core issue #1258 --- Zotlabs/Widget/Activity_order.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Activity_order.php b/Zotlabs/Widget/Activity_order.php index 0e660afc3..27d1a971a 100644 --- a/Zotlabs/Widget/Activity_order.php +++ b/Zotlabs/Widget/Activity_order.php @@ -34,6 +34,7 @@ class Activity_order { break; default: $commentord_active = 'active'; + break; } } else { @@ -78,6 +79,9 @@ class Activity_order { if(x($_GET,'file')) $filter .= '&file=' . $_GET['file']; + if(x($_GET,'pf')) + $filter .= '&pf=' . $_GET['pf']; + // tabs $tabs = []; -- cgit v1.2.3 From d908f53607512b8bfa3fbf65cb6fc9623fab5c63 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 2 Aug 2018 22:49:30 -0700 Subject: add app_options field --- Zotlabs/Lib/Apps.php | 13 ++++++++++--- Zotlabs/Module/Probe.php | 7 +++---- Zotlabs/Module/Zfinger.php | 4 ---- Zotlabs/Update/_1217.php | 22 ++++++++++++++++++++++ 4 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 Zotlabs/Update/_1217.php (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index f7aff1722..9027b13bc 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -927,10 +927,11 @@ class Apps { $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : ''); $darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0); $darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0); + $darray['app_options'] = ((x($arr,'options')) ? intval($arr['options']) : 0); $created = datetime_convert(); - $r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited, app_system, app_plugin, app_deleted ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', %d )", + $r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited, app_system, app_plugin, app_deleted, app_options ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', %d, %d )", dbesc($darray['app_id']), dbesc($darray['app_sig']), dbesc($darray['app_author']), @@ -948,7 +949,8 @@ class Apps { dbesc($created), intval($darray['app_system']), dbesc($darray['app_plugin']), - intval($darray['app_deleted']) + intval($darray['app_deleted']), + intval($darray['app_options']) ); if($r) { @@ -1009,10 +1011,11 @@ class Apps { $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : ''); $darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0); $darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0); + $darray['app_options'] = ((x($arr,'options')) ? intval($arr['options']) : 0); $edited = datetime_convert(); - $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s', app_system = %d, app_plugin = '%s', app_deleted = %d where app_id = '%s' and app_channel = %d", + $r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s', app_system = %d, app_plugin = '%s', app_deleted = %d, app_options = %d where app_id = '%s' and app_channel = %d", dbesc($darray['app_sig']), dbesc($darray['app_author']), dbesc($darray['app_name']), @@ -1028,6 +1031,7 @@ class Apps { intval($darray['app_system']), dbesc($darray['app_plugin']), intval($darray['app_deleted']), + intval($darray['app_options']), dbesc($darray['app_id']), intval($darray['app_channel']) ); @@ -1117,6 +1121,9 @@ class Apps { if($app['app_system']) $ret['system'] = $app['app_system']; + if($app['app_options']) + $ret['options'] = $app['app_options']; + if($app['app_plugin']) $ret['plugin'] = trim($app['app_plugin']); diff --git a/Zotlabs/Module/Probe.php b/Zotlabs/Module/Probe.php index 2e65f107c..2c67c6aae 100644 --- a/Zotlabs/Module/Probe.php +++ b/Zotlabs/Module/Probe.php @@ -27,12 +27,11 @@ class Probe extends \Zotlabs\Web\Controller { $o .= '
';
 			if(! $j['success']) {
-				$o .= sprintf( t('Fetching URL returns error: %1$s'),$res['error'] . "\r\n\r\n");
 				$o .= "https connection failed. Trying again with auto failover to http.\r\n\r\n";
 				$j = \Zotlabs\Zot\Finger::run($addr,$channel,true);
-				if(! $j['success']) 
-					$o .= sprintf( t('Fetching URL returns error: %1$s'),$res['error'] . "\r\n\r\n");
-	
+				if(! $j['success']) {
+					return $o;	
+				}
 			}
 			if($do_import && $j)
 				$x = import_xchan($j);
diff --git a/Zotlabs/Module/Zfinger.php b/Zotlabs/Module/Zfinger.php
index 0f7f6a64b..6ed001df5 100644
--- a/Zotlabs/Module/Zfinger.php
+++ b/Zotlabs/Module/Zfinger.php
@@ -36,10 +36,6 @@ class Zfinger extends \Zotlabs\Web\Controller {
 
 		echo $ret;
 		killme();
-
-
-
-		json_return_and_die($x);
 	
 	}
 	
diff --git a/Zotlabs/Update/_1217.php b/Zotlabs/Update/_1217.php
new file mode 100644
index 000000000..15d2d06b3
--- /dev/null
+++ b/Zotlabs/Update/_1217.php
@@ -0,0 +1,22 @@
+
Date: Mon, 6 Aug 2018 17:43:22 -0700
Subject: bring some Zot6 libraries and interfaces to red/hubzilla

---
 Zotlabs/Lib/Activity.php     | 1725 +++++++++++++++++++++++++
 Zotlabs/Lib/Group.php        |  405 ++++++
 Zotlabs/Lib/Libsync.php      | 1019 +++++++++++++++
 Zotlabs/Lib/Libzot.php       | 2849 ++++++++++++++++++++++++++++++++++++++++++
 Zotlabs/Lib/Libzotdir.php    |  654 ++++++++++
 Zotlabs/Lib/Queue.php        |  278 +++++
 Zotlabs/Lib/Webfinger.php    |  109 ++
 Zotlabs/Lib/Zotfinger.php    |   50 +
 Zotlabs/Module/Zot.php       |   25 +
 Zotlabs/Zot6/Finger.php      |  146 +++
 Zotlabs/Zot6/IHandler.php    |   18 +
 Zotlabs/Zot6/Receiver.php    |  220 ++++
 Zotlabs/Zot6/Zot6Handler.php |  266 ++++
 13 files changed, 7764 insertions(+)
 create mode 100644 Zotlabs/Lib/Activity.php
 create mode 100644 Zotlabs/Lib/Group.php
 create mode 100644 Zotlabs/Lib/Libsync.php
 create mode 100644 Zotlabs/Lib/Libzot.php
 create mode 100644 Zotlabs/Lib/Libzotdir.php
 create mode 100644 Zotlabs/Lib/Queue.php
 create mode 100644 Zotlabs/Lib/Webfinger.php
 create mode 100644 Zotlabs/Lib/Zotfinger.php
 create mode 100644 Zotlabs/Module/Zot.php
 create mode 100644 Zotlabs/Zot6/Finger.php
 create mode 100644 Zotlabs/Zot6/IHandler.php
 create mode 100644 Zotlabs/Zot6/Receiver.php
 create mode 100644 Zotlabs/Zot6/Zot6Handler.php

(limited to 'Zotlabs')

diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
new file mode 100644
index 000000000..6ddbbb9db
--- /dev/null
+++ b/Zotlabs/Lib/Activity.php
@@ -0,0 +1,1725 @@
+ 'Object',
+			'id'   => z_root() . '/thing/' . $r[0]['obj_obj'],
+			'name' => $r[0]['obj_term']
+		];
+
+		if($r[0]['obj_image'])
+			$x['image'] = $r[0]['obj_image'];
+
+		return $x;
+
+	}
+
+	static function fetch_item($x) {
+
+		if (array_key_exists('source',$x)) {
+			// This item is already processed and encoded
+			return $x;
+		}
+
+		$r = q("select * from item where mid = '%s' limit 1",
+			dbesc($x['id'])
+		);
+		if($r) {
+			xchan_query($r,true);
+			$r = fetch_post_tags($r,true);
+			return self::encode_item($r[0]);
+		}
+	}
+
+	static function encode_item_collection($items,$id,$type,$extra = null) {
+
+		$ret = [
+			'id' => z_root() . '/' . $id,
+			'type' => $type,
+			'totalItems' => count($items),
+		];
+		if($extra)
+			$ret = array_merge($ret,$extra);
+
+		if($items) {
+			$x = [];
+			foreach($items as $i) {
+				$t = self::encode_activity($i);
+				if($t)
+					$x[] = $t;
+			}
+			if($type === 'OrderedCollection')
+				$ret['orderedItems'] = $x;
+			else
+				$ret['items'] = $x;
+		}
+
+		return $ret;
+	}
+
+	static function encode_follow_collection($items,$id,$type,$extra = null) {
+
+		$ret = [
+			'id' => z_root() . '/' . $id,
+			'type' => $type,
+			'totalItems' => count($items),
+		];
+		if($extra)
+			$ret = array_merge($ret,$extra);
+
+		if($items) {
+			$x = [];
+			foreach($items as $i) {
+				if($i['xchan_url']) {
+					$x[] = $i['xchan_url'];
+				}
+			}
+
+			if($type === 'OrderedCollection')
+				$ret['orderedItems'] = $x;
+			else
+				$ret['items'] = $x;
+		}
+
+		return $ret;
+	}
+
+
+
+
+	static function encode_item($i) {
+
+		$ret = [];
+
+		$objtype = self::activity_obj_mapper($i['obj_type']);
+
+		if(intval($i['item_deleted'])) {
+			$ret['type'] = 'Tombstone';
+			$ret['formerType'] = $objtype;
+			$ret['id'] = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid']));
+			return $ret;
+		}
+
+		$ret['type'] = $objtype;
+
+		$ret['id']   = ((strpos($i['mid'],'http') === 0) ? $i['mid'] : z_root() . '/item/' . urlencode($i['mid']));
+
+		if($i['title'])
+			$ret['title'] = bbcode($i['title']);
+
+		$ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME);
+		if($i['created'] !== $i['edited'])
+			$ret['updated'] = datetime_convert('UTC','UTC',$i['edited'],ATOM_TIME);
+		if($i['app']) {
+			$ret['instrument'] = [ 'type' => 'Service', 'name' => $i['app'] ];
+		}
+		if($i['location'] || $i['coord']) {
+			$ret['location'] = [ 'type' => 'Place' ];
+			if($i['location']) {
+				$ret['location']['name'] = $i['location'];
+			}
+			if($i['coord']) {
+				$l = explode(' ',$i['coord']);
+				$ret['location']['latitude'] = $l[0];
+				$ret['location']['longitude'] = $l[1];
+			}
+		}
+
+		$ret['attributedTo'] = $i['author']['xchan_url'];
+
+		if($i['id'] != $i['parent']) {
+			$ret['inReplyTo'] = ((strpos($i['parent_mid'],'http') === 0) ? $i['parent_mid'] : z_root() . '/item/' . urlencode($i['parent_mid']));
+		}
+
+		if($i['mimetype'] === 'text/bbcode') {
+			if($i['title'])
+				$ret['name'] = bbcode($i['title']);
+			if($i['summary'])
+				$ret['summary'] = bbcode($i['summary']);
+			$ret['content'] = bbcode($i['body']);
+			$ret['source'] = [ 'content' => $i['body'], 'mediaType' => 'text/bbcode' ];
+		}
+
+		$actor = self::encode_person($i['author'],false);
+		if($actor)
+			$ret['actor'] = $actor;
+		else
+			return [];
+
+		$t = self::encode_taxonomy($i);
+		if($t) {
+			$ret['tag']       = $t;
+		}
+
+		$a = self::encode_attachment($i);
+		if($a) {
+			$ret['attachment'] = $a;
+		}
+
+		return $ret;
+	}
+
+	static function decode_taxonomy($item) {
+
+		$ret = [];
+
+		if($item['tag']) {
+			foreach($item['tag'] as $t) {
+				if(! array_key_exists('type',$t))
+					$t['type'] = 'Hashtag';
+
+				switch($t['type']) {
+					case 'Hashtag':
+						$ret[] = [ 'ttype' => TERM_HASHTAG, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'],0,1) === '#') ? substr($t['name'],1) : $t['name']) ];
+						break;
+
+					case 'Mention':
+						$mention_type = substr($t['name'],0,1);
+						if($mention_type === '!') {
+							$ret[] = [ 'ttype' => TERM_FORUM, 'url' => $t['href'], 'term' => escape_tags(substr($t['name'],1)) ];
+						}
+						else {
+							$ret[] = [ 'ttype' => TERM_MENTION, 'url' => $t['href'], 'term' => escape_tags((substr($t['name'],0,1) === '@') ? substr($t['name'],1) : $t['name']) ];
+						}
+						break;
+	
+					default:
+						break;
+				}
+			}
+		}
+
+		return $ret;
+	}
+
+
+	static function encode_taxonomy($item) {
+
+		$ret = [];
+
+		if($item['term']) {
+			foreach($item['term'] as $t) {
+				switch($t['ttype']) {
+					case TERM_HASHTAG:
+						// An id is required so if we don't have a url in the taxonomy, ignore it and keep going.
+						if($t['url']) {
+							$ret[] = [ 'id' => $t['url'], 'name' => '#' . $t['term'] ];
+						}
+						break;
+
+					case TERM_FORUM:
+						$ret[] = [ 'type' => 'Mention', 'href' => $t['url'], 'name' => '!' . $t['term'] ];
+						break;
+
+					case TERM_MENTION:
+						$ret[] = [ 'type' => 'Mention', 'href' => $t['url'], 'name' => '@' . $t['term'] ];
+						break;
+	
+					default:
+						break;
+				}
+			}
+		}
+
+		return $ret;
+	}
+
+	static function encode_attachment($item) {
+
+		$ret = [];
+
+		if($item['attach']) {
+			$atts = json_decode($item['attach'],true);
+			if($atts) {
+				foreach($atts as $att) {
+					if(strpos($att['type'],'image')) {
+						$ret[] = [ 'type' => 'Image', 'url' => $att['href'] ];
+					}
+					else {
+						$ret[] = [ 'type' => 'Link', 'mediaType' => $att['type'], 'href' => $att['href'] ];
+					}
+				}
+			}
+		}
+
+		return $ret;
+	}
+
+
+	static function decode_attachment($item) {
+
+		$ret = [];
+
+		if($item['attachment']) {
+			foreach($item['attachment'] as $att) {
+				$entry = [];
+				if($att['href'])
+					$entry['href'] = $att['href'];
+				elseif($att['url'])
+					$entry['href'] = $att['url'];
+				if($att['mediaType'])
+					$entry['type'] = $att['mediaType'];
+				elseif($att['type'] === 'Image')
+					$entry['type'] = 'image/jpeg';
+				if($entry)
+					$ret[] = $entry;
+			}
+		}
+
+		return $ret;
+	}
+
+
+
+	static function encode_activity($i) {
+
+		$ret   = [];
+		$reply = false;
+
+		if(intval($i['item_deleted'])) {
+			$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']));
+			return $ret;
+		}
+
+		$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'])
+			$ret['name'] = html2plain(bbcode($i['title']));
+
+		if($i['summary'])
+			$ret['summary'] = bbcode($i['summary']);
+
+		if($ret['type'] === 'Announce') {
+			$tmp = preg_replace('/\[share(.*?)\[\/share\]/ism',EMPTY_STR, $i['body']);
+			$ret['content'] = bbcode($tmp);
+			$ret['source'] = [
+				'content' => $i['body'],
+				'mediaType' => 'text/bbcode'
+			];
+		}
+
+		$ret['published'] = datetime_convert('UTC','UTC',$i['created'],ATOM_TIME);
+		if($i['created'] !== $i['edited'])
+			$ret['updated'] = datetime_convert('UTC','UTC',$i['edited'],ATOM_TIME);
+		if($i['app']) {
+			$ret['instrument'] = [ 'type' => 'Service', 'name' => $i['app'] ];
+		}
+		if($i['location'] || $i['coord']) {
+			$ret['location'] = [ 'type' => 'Place' ];
+			if($i['location']) {
+				$ret['location']['name'] = $i['location'];
+			}
+			if($i['coord']) {
+				$l = explode(' ',$i['coord']);
+				$ret['location']['latitude'] = $l[0];
+				$ret['location']['longitude'] = $l[1];
+			}
+		}
+
+		if($i['id'] != $i['parent']) {
+			$ret['inReplyTo'] = ((strpos($i['parent_mid'],'http') === 0) ? $i['parent_mid'] : z_root() . '/item/' . urlencode($i['parent_mid']));
+			$reply = true;
+
+			if($i['item_private']) {
+				$d = q("select xchan_url, xchan_addr, xchan_name from item left join xchan on xchan_hash = author_xchan where id = %d limit 1",
+					intval($i['parent'])
+				);
+				if($d) {
+					$is_directmessage = false;
+					$recips = get_iconfig($i['parent'], 'activitypub', 'recips');
+
+					if(in_array($i['author']['xchan_url'], $recips['to'])) {
+						$reply_url = $d[0]['xchan_url'];
+						$is_directmessage = true;
+					}
+					else {
+						$reply_url = z_root() . '/followers/' . substr($i['author']['xchan_addr'],0,strpos($i['author']['xchan_addr'],'@'));
+					}
+
+					$reply_addr = (($d[0]['xchan_addr']) ? $d[0]['xchan_addr'] : $d[0]['xchan_name']);
+				}
+			}
+
+		}
+
+		$actor = self::encode_person($i['author'],false);
+		if($actor)
+			$ret['actor'] = $actor;
+		else
+			return []; 
+
+		if($i['obj']) {
+			if(! is_array($i['obj'])) {
+				$i['obj'] = json_decode($i['obj'],true);
+			}
+			$obj = self::encode_object($i['obj']);
+			if($obj)
+				$ret['object'] = $obj;
+			else
+				return [];
+		}
+		else {
+			$obj = self::encode_item($i);
+			if($obj)
+				$ret['object'] = $obj;
+			else
+				return [];
+		}
+
+		if($i['target']) {
+			if(! is_array($i['target'])) {
+				$i['target'] = json_decode($i['target'],true);
+			}
+			$tgt = self::encode_object($i['target']);
+			if($tgt)
+				$ret['target'] = $tgt;
+			else
+				return [];
+		}
+
+		return $ret;
+	}
+
+	static function map_mentions($i) {
+		if(! $i['term']) {
+			return [];
+		}
+
+		$list = [];
+
+		foreach ($i['term'] as $t) {
+			if($t['ttype'] == TERM_MENTION) {
+				$list[] = $t['url'];
+			}
+		}
+
+		return $list;
+	}
+
+	static function map_acl($i,$mentions = false) {
+
+		$private = false;
+		$list = [];
+		$x = collect_recipients($i,$private);
+		if($x) {
+			stringify_array_elms($x);
+			if(! $x)
+				return;
+
+			$strict = (($mentions) ? true : get_config('activitypub','compliance'));
+
+			$sql_extra = (($strict) ? " and xchan_network = 'activitypub' " : '');
+
+			$details = q("select xchan_url, xchan_addr, xchan_name from xchan where xchan_hash in (" . implode(',',$x) . ") $sql_extra");
+
+			if($details) {
+				foreach($details as $d) {
+					if($mentions) {
+						$list[] = [ 'type' => 'Mention', 'href' => $d['xchan_url'], 'name' => '@' . (($d['xchan_addr']) ? $d['xchan_addr'] : $d['xchan_name']) ];
+					}
+					else { 
+						$list[] = $d['xchan_url'];
+					}
+				}
+			}
+		}
+
+		return $list;
+
+	}
+
+
+	static function encode_person($p, $extended = true) {
+
+		if(! $p['xchan_url'])
+			return [];
+
+		if(! $extended) {
+			return $p['xchan_url'];
+		}
+		$ret = [];
+
+		$ret['type']  = 'Person';
+		$ret['id']    = $p['xchan_url'];
+		if($p['xchan_addr'] && strpos($p['xchan_addr'],'@'))
+			$ret['preferredUsername'] = substr($p['xchan_addr'],0,strpos($p['xchan_addr'],'@'));
+		$ret['name']  = $p['xchan_name'];
+		$ret['updated'] = datetime_convert('UTC','UTC',$p['xchan_name_date'],ATOM_TIME);
+		$ret['icon']  = [
+			'type'      => 'Image',
+			'mediaType' => (($p['xchan_photo_mimetype']) ? $p['xchan_photo_mimetype'] : 'image/png' ),
+			'updated'   => datetime_convert('UTC','UTC',$p['xchan_photo_date'],ATOM_TIME),
+			'url'       => $p['xchan_photo_l'],
+			'height'    => 300,
+			'width'     => 300,
+		];
+		$ret['url'] = [
+			[ 
+				'type'      => 'Link',
+				'mediaType' => 'text/html',
+				'href'      => $p['xchan_url']
+			],
+			[
+				'type'      => 'Link',
+				'mediaType' => 'text/x-zot+json',
+				'href'      => $p['xchan_url']
+			]
+		];
+
+		$arr = [ 'xchan' => $p, 'encoded' => $ret ];
+		call_hooks('encode_person', $arr);
+		$ret = $arr['encoded'];
+
+
+		return $ret;
+	}
+
+
+	static function activity_mapper($verb) {
+
+		if(strpos($verb,'/') === false) {
+			return $verb;
+		}
+
+		$acts = [
+			'http://activitystrea.ms/schema/1.0/post'      => 'Create',
+			'http://activitystrea.ms/schema/1.0/share'     => 'Announce',
+			'http://activitystrea.ms/schema/1.0/update'    => 'Update',
+			'http://activitystrea.ms/schema/1.0/like'      => 'Like',
+			'http://activitystrea.ms/schema/1.0/favorite'  => 'Like',
+			'http://purl.org/zot/activity/dislike'         => 'Dislike',
+			'http://activitystrea.ms/schema/1.0/tag'       => 'Add',
+			'http://activitystrea.ms/schema/1.0/follow'    => 'Follow',
+			'http://activitystrea.ms/schema/1.0/unfollow'  => 'Unfollow',
+		];
+
+
+		if(array_key_exists($verb,$acts) && $acts[$verb]) {
+			return $acts[$verb];
+		}
+
+		// Reactions will just map to normal activities
+
+		if(strpos($verb,ACTIVITY_REACT) !== false)
+			return 'Create';
+		if(strpos($verb,ACTIVITY_MOOD) !== false)
+			return 'Create';
+
+		if(strpos($verb,ACTIVITY_POKE) !== false)
+			return 'Activity';
+
+		// We should return false, however this will trigger an uncaught execption  and crash 
+		// the delivery system if encountered by the JSON-LDSignature library
+ 
+		logger('Unmapped activity: ' . $verb);
+		return 'Create';
+	//	return false;
+}
+
+
+	static function activity_obj_mapper($obj) {
+
+		if(strpos($obj,'/') === false) {
+			return $obj;
+		}
+
+		$objs = [
+			'http://activitystrea.ms/schema/1.0/note'           => 'Note',
+			'http://activitystrea.ms/schema/1.0/comment'        => 'Note',
+			'http://activitystrea.ms/schema/1.0/person'         => 'Person',
+			'http://purl.org/zot/activity/profile'              => 'Profile',
+			'http://activitystrea.ms/schema/1.0/photo'          => 'Image',
+			'http://activitystrea.ms/schema/1.0/profile-photo'  => 'Icon',
+			'http://activitystrea.ms/schema/1.0/event'          => 'Event',
+			'http://activitystrea.ms/schema/1.0/wiki'           => 'Document',
+			'http://purl.org/zot/activity/location'             => 'Place',
+			'http://purl.org/zot/activity/chessgame'            => 'Game',
+			'http://purl.org/zot/activity/tagterm'              => 'zot:Tag',
+			'http://purl.org/zot/activity/thing'                => 'Object',
+			'http://purl.org/zot/activity/file'                 => 'zot:File',
+			'http://purl.org/zot/activity/mood'                 => 'zot:Mood',
+		
+		];
+
+		if(array_key_exists($obj,$objs)) {
+			return $objs[$obj];
+		}
+
+		logger('Unmapped activity object: ' . $obj);
+		return 'Note';
+
+		//	return false;
+
+	}
+
+
+	static function follow($channel,$act) {
+
+		$contact = null;
+		$their_follow_id = null;
+
+		/*
+		 * 
+		 * if $act->type === 'Follow', actor is now following $channel 
+		 * if $act->type === 'Accept', actor has approved a follow request from $channel 
+		 *	 
+		 */
+
+		$person_obj = $act->actor;
+
+		if($act->type === 'Follow') {
+			$their_follow_id  = $act->id;
+		}
+		elseif($act->type === 'Accept') {
+			$my_follow_id = z_root() . '/follow/' . $contact['id'];
+		}
+	
+		if(is_array($person_obj)) {
+
+			// store their xchan and hubloc
+
+			self::actor_store($person_obj['id'],$person_obj);
+
+			// Find any existing abook record 
+
+			$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d limit 1",
+				dbesc($person_obj['id']),
+				intval($channel['channel_id'])
+			);
+			if($r) {
+				$contact = $r[0];
+			}
+		}
+
+		$x = \Zotlabs\Access\PermissionRoles::role_perms('social');
+		$p = \Zotlabs\Access\Permissions::FilledPerms($x['perms_connect']);
+		$their_perms = \Zotlabs\Access\Permissions::serialise($p);
+
+		if($contact && $contact['abook_id']) {
+
+			// A relationship of some form already exists on this site. 
+
+			switch($act->type) {
+
+				case 'Follow':
+
+					// A second Follow request, but we haven't approved the first one
+
+					if($contact['abook_pending']) {
+						return;
+					}
+
+					// We've already approved them or followed them first
+					// Send an Accept back to them
+
+					set_abconfig($channel['channel_id'],$person_obj['id'],'pubcrawl','their_follow_id', $their_follow_id);
+					\Zotlabs\Daemon\Master::Summon([ 'Notifier', 'permissions_accept', $contact['abook_id'] ]);
+					return;
+
+				case 'Accept':
+
+					// They accepted our Follow request - set default permissions
+	
+					set_abconfig($channel['channel_id'],$contact['abook_xchan'],'system','their_perms',$their_perms);
+
+					$abook_instance = $contact['abook_instance'];
+	
+					if(strpos($abook_instance,z_root()) === false) {
+						if($abook_instance) 
+							$abook_instance .= ',';
+						$abook_instance .= z_root();
+
+						$r = q("update abook set abook_instance = '%s', abook_not_here = 0 
+							where abook_id = %d and abook_channel = %d",
+							dbesc($abook_instance),
+							intval($contact['abook_id']),
+							intval($channel['channel_id'])
+						);
+					}
+		
+					return;
+				default:
+					return;
+	
+			}
+		}
+
+		// No previous relationship exists.
+
+		if($act->type === 'Accept') {
+			// This should not happen unless we deleted the connection before it was accepted.
+			return;
+		}
+
+		// From here on out we assume a Follow activity to somebody we have no existing relationship with
+
+		set_abconfig($channel['channel_id'],$person_obj['id'],'pubcrawl','their_follow_id', $their_follow_id);
+
+		// The xchan should have been created by actor_store() above
+
+		$r = q("select * from xchan where xchan_hash = '%s' and xchan_network = 'activitypub' limit 1",
+			dbesc($person_obj['id'])
+		);
+
+		if(! $r) {
+			logger('xchan not found for ' . $person_obj['id']);
+			return;
+		}
+		$ret = $r[0];
+
+		$p = \Zotlabs\Access\Permissions::connect_perms($channel['channel_id']);
+		$my_perms  = \Zotlabs\Access\Permissions::serialise($p['perms']);
+		$automatic = $p['automatic'];
+
+		$closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness',80);
+
+		$r = abook_store_lowlevel(
+			[
+				'abook_account'   => intval($channel['channel_account_id']),
+				'abook_channel'   => intval($channel['channel_id']),
+				'abook_xchan'     => $ret['xchan_hash'],
+				'abook_closeness' => intval($closeness),
+				'abook_created'   => datetime_convert(),
+				'abook_updated'   => datetime_convert(),
+				'abook_connected' => datetime_convert(),
+				'abook_dob'       => NULL_DATE,
+				'abook_pending'   => intval(($automatic) ? 0 : 1),
+				'abook_instance'  => z_root()
+			]
+		);
+		
+		if($my_perms)
+			set_abconfig($channel['channel_id'],$ret['xchan_hash'],'system','my_perms',$my_perms);
+
+		if($their_perms)
+			set_abconfig($channel['channel_id'],$ret['xchan_hash'],'system','their_perms',$their_perms);
+
+
+		if($r) {
+			logger("New ActivityPub follower for {$channel['channel_name']}");
+
+			$new_connection = q("select * from abook left join xchan on abook_xchan = xchan_hash left join hubloc on hubloc_hash = xchan_hash where abook_channel = %d and abook_xchan = '%s' order by abook_created desc limit 1",
+				intval($channel['channel_id']),
+				dbesc($ret['xchan_hash'])
+			);
+			if($new_connection) {
+				\Zotlabs\Lib\Enotify::submit(
+					[
+						'type'	       => NOTIFY_INTRO,
+						'from_xchan'   => $ret['xchan_hash'],
+						'to_xchan'     => $channel['channel_hash'],
+						'link'         => z_root() . '/connedit/' . $new_connection[0]['abook_id'],
+					]
+				);
+
+				if($my_perms && $automatic) {
+					// send an Accept for this Follow activity
+					\Zotlabs\Daemon\Master::Summon([ 'Notifier', 'permissions_accept', $new_connection[0]['abook_id'] ]);
+					// Send back a Follow notification to them
+					\Zotlabs\Daemon\Master::Summon([ 'Notifier', 'permissions_create', $new_connection[0]['abook_id'] ]);
+				}
+
+				$clone = array();
+				foreach($new_connection[0] as $k => $v) {
+					if(strpos($k,'abook_') === 0) {
+						$clone[$k] = $v;
+					}
+				}
+				unset($clone['abook_id']);
+				unset($clone['abook_account']);
+				unset($clone['abook_channel']);
+		
+				$abconfig = load_abconfig($channel['channel_id'],$clone['abook_xchan']);
+
+				if($abconfig)
+					$clone['abconfig'] = $abconfig;
+
+				Libsync::build_sync_packet($channel['channel_id'], [ 'abook' => array($clone) ] );
+			}
+		}
+
+
+		/* If there is a default group for this channel and permissions are automatic, add this member to it */
+
+		if($channel['channel_default_group'] && $automatic) {
+			$g = Group::rec_byhash($channel['channel_id'],$channel['channel_default_group']);
+			if($g)
+				Group::member_add($channel['channel_id'],'',$ret['xchan_hash'],$g['id']);
+		}
+
+
+		return;
+
+	}
+
+
+	static function unfollow($channel,$act) {
+
+		$contact = null;
+
+		/* @FIXME This really needs to be a signed request. */
+
+		/* actor is unfollowing $channel */
+
+		$person_obj = $act->actor;
+
+		if(is_array($person_obj)) {
+
+			$r = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_xchan = '%s' and abook_channel = %d limit 1",
+				dbesc($person_obj['id']),
+				intval($channel['channel_id'])
+			);
+			if($r) {
+				// remove all permissions they provided
+				del_abconfig($channel['channel_id'],$r[0]['xchan_hash'],'system','their_perms',EMPTY_STR);
+			}
+		}
+
+		return;
+	}
+
+
+
+
+	static function actor_store($url,$person_obj) {
+
+		if(! is_array($person_obj))
+			return;
+
+		$name = $person_obj['name'];
+		if(! $name)
+			$name = $person_obj['preferredUsername'];
+		if(! $name)
+			$name = t('Unknown');
+
+		if($person_obj['icon']) {
+			if(is_array($person_obj['icon'])) {
+				if(array_key_exists('url',$person_obj['icon']))
+					$icon = $person_obj['icon']['url'];
+				else
+					$icon = $person_obj['icon'][0]['url'];
+			}
+			else
+				$icon = $person_obj['icon'];
+		}
+
+		if(is_array($person_obj['url']) && array_key_exists('href', $person_obj['url']))
+			$profile = $person_obj['url']['href'];
+		else
+			$profile = $url;
+
+
+		$inbox = $person_obj['inbox'];
+
+		$collections = [];
+
+		if($inbox) {
+			$collections['inbox'] = $inbox;
+			if($person_obj['outbox'])
+				$collections['outbox'] = $person_obj['outbox'];
+			if($person_obj['followers'])
+				$collections['followers'] = $person_obj['followers'];
+			if($person_obj['following'])
+				$collections['following'] = $person_obj['following'];
+			if($person_obj['endpoints'] && $person_obj['endpoints']['sharedInbox'])
+				$collections['sharedInbox'] = $person_obj['endpoints']['sharedInbox'];
+		}
+
+		if(array_key_exists('publicKey',$person_obj) && array_key_exists('publicKeyPem',$person_obj['publicKey'])) {
+			if($person_obj['id'] === $person_obj['publicKey']['owner']) {
+				$pubkey = $person_obj['publicKey']['publicKeyPem'];
+				if(strstr($pubkey,'RSA ')) {
+					$pubkey = rsatopem($pubkey);
+				}
+			}
+		}
+
+		$r = q("select * from xchan where xchan_hash = '%s' limit 1",
+			dbesc($url)
+		);
+		if(! $r) {
+			// create a new record
+			$r = xchan_store_lowlevel(
+				[
+					'xchan_hash'         => $url,
+					'xchan_guid'         => $url,
+					'xchan_pubkey'       => $pubkey,
+					'xchan_addr'         => '',
+					'xchan_url'          => $profile,
+					'xchan_name'         => $name,
+					'xchan_name_date'    => datetime_convert(),
+					'xchan_network'      => 'activitypub'
+				]
+			);
+		}
+		else {
+
+			// Record exists. Cache existing records for one week at most
+			// then refetch to catch updated profile photos, names, etc. 
+
+			$d = datetime_convert('UTC','UTC','now - 1 week');
+			if($r[0]['xchan_name_date'] > $d)
+				return;
+
+			// update existing record
+			$r = q("update xchan set xchan_name = '%s', xchan_pubkey = '%s', xchan_network = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
+				dbesc($name),
+				dbesc($pubkey),
+				dbesc('activitypub'),
+				dbesc(datetime_convert()),
+				dbesc($url)
+			);
+		}
+
+		if($collections) {
+			set_xconfig($url,'activitypub','collections',$collections);
+		}
+
+		$r = q("select * from hubloc where hubloc_hash = '%s' limit 1",
+			dbesc($url)
+		);
+
+
+		$m = parse_url($url);
+		if($m) {
+			$hostname = $m['host'];
+			$baseurl = $m['scheme'] . '://' . $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
+		}
+
+		if(! $r) {
+			$r = hubloc_store_lowlevel(
+				[
+					'hubloc_guid'     => $url,
+					'hubloc_hash'     => $url,
+					'hubloc_addr'     => '',
+					'hubloc_network'  => 'activitypub',
+					'hubloc_url'      => $baseurl,
+					'hubloc_host'     => $hostname,
+					'hubloc_callback' => $inbox,
+					'hubloc_updated'  => datetime_convert(),
+					'hubloc_primary'  => 1
+				]
+			);
+		}
+
+		if(! $icon)
+			$icon = z_root() . '/' . get_default_profile_photo(300);
+
+		$photos = import_xchan_photo($icon,$url);
+		$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
+			dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])),
+			dbesc($photos[0]),
+			dbesc($photos[1]),
+			dbesc($photos[2]),
+			dbesc($photos[3]),
+			dbesc($url)
+		);
+
+	}
+
+
+	static function create_action($channel,$observer_hash,$act) {
+
+		if(in_array($act->obj['type'], [ 'Note', 'Article', 'Video' ])) {
+			self::create_note($channel,$observer_hash,$act);
+		}
+
+
+	}
+
+	static function announce_action($channel,$observer_hash,$act) {
+
+		if(in_array($act->type, [ 'Announce' ])) {
+			self::announce_note($channel,$observer_hash,$act);
+		}
+
+	}
+
+
+	static function like_action($channel,$observer_hash,$act) {
+
+		if(in_array($act->obj['type'], [ 'Note', 'Article', 'Video' ])) {
+			self::like_note($channel,$observer_hash,$act);
+		}
+
+
+	}
+
+	// sort function width decreasing
+
+	static function as_vid_sort($a,$b) {
+		if($a['width'] === $b['width'])
+			return 0;
+		return (($a['width'] > $b['width']) ? -1 : 1);
+	}
+
+	static function create_note($channel,$observer_hash,$act) {
+
+		$s = [];
+
+		// Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field.
+		// They are hidden in the public timeline if the public inbox is listed in the 'cc' field.
+		// This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point.
+		$pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false);
+		$is_sys_channel = is_sys_channel($channel['channel_id']);
+
+		$parent = ((array_key_exists('inReplyTo',$act->obj)) ? urldecode($act->obj['inReplyTo']) : '');
+		if($parent) {
+
+			$r = q("select * from item where uid = %d and ( mid = '%s' or  mid = '%s' ) limit 1",
+				intval($channel['channel_id']),
+				dbesc($parent),
+				dbesc(basename($parent))
+			);
+
+			if(! $r) {
+				logger('parent not found.');
+				return;
+			}
+
+			if($r[0]['owner_xchan'] === $channel['channel_hash']) {
+				if(! perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && ! ($is_sys_channel && $pubstream)) {
+					logger('no comment permission.');
+					return;
+				}
+			}
+
+			$s['parent_mid'] = $r[0]['mid'];
+			$s['owner_xchan'] = $r[0]['owner_xchan'];
+			$s['author_xchan'] = $observer_hash;
+
+		}
+		else {
+			if(! perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && ! ($is_sys_channel && $pubstream)) {
+				logger('no permission');
+				return;
+			}
+			$s['owner_xchan'] = $s['author_xchan'] = $observer_hash;
+		}
+	
+		$abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+			dbesc($observer_hash),
+			intval($channel['channel_id'])
+		);
+	
+		$content = self::get_content($act->obj);
+
+		if(! $content) {
+			logger('no content');
+			return;
+		}
+
+		$s['aid'] = $channel['channel_account_id'];
+		$s['uid'] = $channel['channel_id'];
+		$s['mid'] = urldecode($act->obj['id']);
+		$s['plink'] = urldecode($act->obj['id']);
+
+
+		if($act->data['published']) {
+			$s['created'] = datetime_convert('UTC','UTC',$act->data['published']);
+		}
+		elseif($act->obj['published']) {
+			$s['created'] = datetime_convert('UTC','UTC',$act->obj['published']);
+		}
+		if($act->data['updated']) {
+			$s['edited'] = datetime_convert('UTC','UTC',$act->data['updated']);
+		}
+		elseif($act->obj['updated']) {
+			$s['edited'] = datetime_convert('UTC','UTC',$act->obj['updated']);
+		}
+
+		if(! $s['created'])
+			$s['created'] = datetime_convert();
+
+		if(! $s['edited'])
+			$s['edited'] = $s['created'];
+
+
+		if(! $s['parent_mid'])
+			$s['parent_mid'] = $s['mid'];
+
+	
+		$s['title']    = self::bb_content($content,'name');
+		$s['summary']  = self::bb_content($content,'summary'); 
+		$s['body']     = self::bb_content($content,'content');
+		$s['verb']     = ACTIVITY_POST;
+		$s['obj_type'] = ACTIVITY_OBJ_NOTE;
+
+		$instrument = $act->get_property_obj('instrument');
+		if(! $instrument)
+			$instrument = $act->get_property_obj('instrument',$act->obj);
+
+		if($instrument && array_key_exists('type',$instrument) 
+			&& $instrument['type'] === 'Service' && array_key_exists('name',$instrument)) {
+			$s['app'] = escape_tags($instrument['name']);
+		}
+
+		if($channel['channel_system']) {
+			if(! \Zotlabs\Lib\MessageFilter::evaluate($s,get_config('system','pubstream_incl'),get_config('system','pubstream_excl'))) {
+				logger('post is filtered');
+				return;
+			}
+		}
+
+
+		if($abook) {
+			if(! post_is_importable($s,$abook[0])) {
+				logger('post is filtered');
+				return;
+			}
+		}
+
+		if($act->obj['conversation']) {
+			set_iconfig($s,'ostatus','conversation',$act->obj['conversation'],1);
+		}
+
+		$a = self::decode_taxonomy($act->obj);
+		if($a) {
+			$s['term'] = $a;
+		}
+
+		$a = self::decode_attachment($act->obj);
+		if($a) {
+			$s['attach'] = $a;
+		}
+
+		if($act->obj['type'] === 'Note' && $s['attach']) {
+			$s['body'] .= self::bb_attach($s['attach']);
+		}
+
+		// we will need a hook here to extract magnet links e.g. peertube
+		// right now just link to the largest mp4 we find that will fit in our
+		// standard content region
+
+		if($act->obj['type'] === 'Video') {
+
+			$vtypes = [
+				'video/mp4',
+				'video/ogg',
+				'video/webm'
+			];
+
+			$mps = [];
+			if(array_key_exists('url',$act->obj) && is_array($act->obj['url'])) {
+				foreach($act->obj['url'] as $vurl) {
+					if(in_array($vurl['mimeType'], $vtypes)) {
+						if(! array_key_exists('width',$vurl)) {
+							$vurl['width'] = 0;
+						}
+						$mps[] = $vurl;
+					}
+				}
+			}
+			if($mps) {
+				usort($mps,'as_vid_sort');
+				foreach($mps as $m) {
+					if(intval($m['width']) < 500) {
+						$s['body'] .= "\n\n" . '[video]' . $m['href'] . '[/video]';
+						break;
+					}
+				}
+			}
+		}
+
+		if($act->recips && (! in_array(ACTIVITY_PUBLIC_INBOX,$act->recips)))
+			$s['item_private'] = 1;
+
+		set_iconfig($s,'activitypub','recips',$act->raw_recips);
+		if($parent) {
+			set_iconfig($s,'activitypub','rawmsg',$act->raw,1);
+		}
+
+		$x = null;
+
+		$r = q("select created, edited from item where mid = '%s' and uid = %d limit 1",
+			dbesc($s['mid']),
+			intval($s['uid'])
+		);
+		if($r) {
+			if($s['edited'] > $r[0]['edited']) {
+				$x = item_store_update($s);
+			}
+			else {
+				return;
+			}
+		}
+		else {
+			$x = item_store($s);
+		}
+
+		if(is_array($x) && $x['item_id']) {
+			if($parent) {
+				if($s['owner_xchan'] === $channel['channel_hash']) {
+					// We are the owner of this conversation, so send all received comments back downstream
+					Zotlabs\Daemon\Master::Summon(array('Notifier','comment-import',$x['item_id']));
+				}
+				$r = q("select * from item where id = %d limit 1",
+					intval($x['item_id'])
+				);
+				if($r) {
+					send_status_notifications($x['item_id'],$r[0]);
+				}
+			}
+			sync_an_item($channel['channel_id'],$x['item_id']);
+		}
+
+	}
+
+
+	static function decode_note($act) {
+
+		$s = [];
+
+
+
+		$content = self::get_content($act->obj);
+
+		$s['owner_xchan']  = $act->actor['id'];
+		$s['author_xchan'] = $act->actor['id'];
+
+		$s['mid']        = $act->id;
+		$s['parent_mid'] = $act->parent_id;
+
+
+		if($act->data['published']) {
+			$s['created'] = datetime_convert('UTC','UTC',$act->data['published']);
+		}
+		elseif($act->obj['published']) {
+			$s['created'] = datetime_convert('UTC','UTC',$act->obj['published']);
+		}
+		if($act->data['updated']) {
+			$s['edited'] = datetime_convert('UTC','UTC',$act->data['updated']);
+		}
+		elseif($act->obj['updated']) {
+			$s['edited'] = datetime_convert('UTC','UTC',$act->obj['updated']);
+		}
+
+		if(! $s['created'])
+			$s['created'] = datetime_convert();
+
+		if(! $s['edited'])
+			$s['edited'] = $s['created'];
+
+		if(in_array($act->type,['Announce'])) {
+			$root_content = self::get_content($act->raw);
+
+			$s['title']    = self::bb_content($root_content,'name');
+			$s['summary']  = self::bb_content($root_content,'summary');
+			$s['body']     = (self::bb_content($root_content,'bbcode') ? : self::bb_content($root_content,'content'));
+
+			if(strpos($s['body'],'[share') === false) {
+
+				// @fixme - error check and set defaults
+
+				$name = urlencode($act->obj['actor']['name']);
+				$profile = $act->obj['actor']['id'];
+				$photo = $act->obj['icon']['url'];
+
+				$s['body'] .= "\r\n[share author='" . $name .
+					"' profile='" . $profile .
+					"' avatar='" . $photo . 
+					"' link='" . $act->obj['id'] .
+					"' auth='" . ((is_matrix_url($act->obj['id'])) ? 'true' : 'false' ) . 
+					"' posted='" . $act->obj['published'] . 
+					"' message_id='" . $act->obj['id'] . 
+				"']";
+			}
+		}
+		else {
+			$s['title']    = self::bb_content($content,'name');
+			$s['summary']  = self::bb_content($content,'summary');
+			$s['body']     = (self::bb_content($content,'bbcode') ? : self::bb_content($content,'content'));
+		}
+
+		$s['verb']     = self::activity_mapper($act->type);
+
+		if($act->type === 'Tombstone') {
+			$s['item_deleted'] = 1;
+		}
+
+		$s['obj_type'] = self::activity_obj_mapper($act->obj['type']);
+		$s['obj']      = $act->obj;
+
+		$instrument = $act->get_property_obj('instrument');
+		if(! $instrument)
+			$instrument = $act->get_property_obj('instrument',$act->obj);
+
+		if($instrument && array_key_exists('type',$instrument) 
+			&& $instrument['type'] === 'Service' && array_key_exists('name',$instrument)) {
+			$s['app'] = escape_tags($instrument['name']);
+		}
+
+		$a = self::decode_taxonomy($act->obj);
+		if($a) {
+			$s['term'] = $a;
+		}
+
+		$a = self::decode_attachment($act->obj);
+		if($a) {
+			$s['attach'] = $a;
+		}
+
+		// we will need a hook here to extract magnet links e.g. peertube
+		// right now just link to the largest mp4 we find that will fit in our
+		// standard content region
+
+		if($act->obj['type'] === 'Video') {
+
+			$vtypes = [
+				'video/mp4',
+				'video/ogg',
+				'video/webm'
+			];
+
+			$mps = [];
+			if(array_key_exists('url',$act->obj) && is_array($act->obj['url'])) {
+				foreach($act->obj['url'] as $vurl) {
+					if(in_array($vurl['mimeType'], $vtypes)) {
+						if(! array_key_exists('width',$vurl)) {
+							$vurl['width'] = 0;
+						}
+						$mps[] = $vurl;
+					}
+				}
+			}
+			if($mps) {
+				usort($mps,'as_vid_sort');
+				foreach($mps as $m) {
+					if(intval($m['width']) < 500) {
+						$s['body'] .= "\n\n" . '[video]' . $m['href'] . '[/video]';
+						break;
+					}
+				}
+			}
+		}
+
+		if($act->recips && (! in_array(ACTIVITY_PUBLIC_INBOX,$act->recips)))
+			$s['item_private'] = 1;
+
+		set_iconfig($s,'activitypub','recips',$act->raw_recips);
+
+		if($parent) {
+			set_iconfig($s,'activitypub','rawmsg',$act->raw,1);
+		}
+
+		return $s;
+
+	}
+
+
+
+	static function announce_note($channel,$observer_hash,$act) {
+
+		$s = [];
+
+		$is_sys_channel = is_sys_channel($channel['channel_id']);
+
+		// Mastodon only allows visibility in public timelines if the public inbox is listed in the 'to' field.
+		// They are hidden in the public timeline if the public inbox is listed in the 'cc' field.
+		// This is not part of the activitypub protocol - we might change this to show all public posts in pubstream at some point.
+		$pubstream = ((is_array($act->obj) && array_key_exists('to', $act->obj) && in_array(ACTIVITY_PUBLIC_INBOX, $act->obj['to'])) ? true : false);
+
+		if(! perm_is_allowed($channel['channel_id'],$observer_hash,'send_stream') && ! ($is_sys_channel && $pubstream)) {
+			logger('no permission');
+			return;
+		}
+
+		$content = self::get_content($act->obj);
+
+		if(! $content) {
+			logger('no content');
+			return;
+		}
+
+		$s['owner_xchan'] = $s['author_xchan'] = $observer_hash;
+
+		$s['aid'] = $channel['channel_account_id'];
+		$s['uid'] = $channel['channel_id'];
+		$s['mid'] = urldecode($act->obj['id']);
+		$s['plink'] = urldecode($act->obj['id']);
+
+		if(! $s['created'])
+			$s['created'] = datetime_convert();
+
+		if(! $s['edited'])
+			$s['edited'] = $s['created'];
+
+
+		$s['parent_mid'] = $s['mid'];
+
+		$s['verb']     = ACTIVITY_POST;
+		$s['obj_type'] = ACTIVITY_OBJ_NOTE;
+		$s['app']      = t('ActivityPub');
+
+		if($channel['channel_system']) {
+			if(! \Zotlabs\Lib\MessageFilter::evaluate($s,get_config('system','pubstream_incl'),get_config('system','pubstream_excl'))) {
+				logger('post is filtered');
+				return;
+			}
+		}
+
+		$abook = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+			dbesc($observer_hash),
+			intval($channel['channel_id'])
+		);
+
+		if($abook) {
+			if(! post_is_importable($s,$abook[0])) {
+				logger('post is filtered');
+				return;
+			}
+		}
+
+		if($act->obj['conversation']) {
+			set_iconfig($s,'ostatus','conversation',$act->obj['conversation'],1);
+		}
+
+		$a = self::decode_taxonomy($act->obj);
+		if($a) {
+			$s['term'] = $a;
+		}
+
+		$a = self::decode_attachment($act->obj);
+		if($a) {
+			$s['attach'] = $a;
+		}
+
+		$body = "[share author='" . urlencode($act->sharee['name']) . 
+			"' profile='" . $act->sharee['url'] . 
+			"' avatar='" . $act->sharee['photo_s'] . 
+			"' link='" . ((is_array($act->obj['url'])) ? $act->obj['url']['href'] : $act->obj['url']) . 
+			"' auth='" . ((is_matrix_url($act->obj['url'])) ? 'true' : 'false' ) . 
+			"' posted='" . $act->obj['published'] . 
+			"' message_id='" . $act->obj['id'] . 
+		"']";
+
+		if($content['name'])
+			$body .= self::bb_content($content,'name') . "\r\n";
+
+		$body .= self::bb_content($content,'content');
+
+		if($act->obj['type'] === 'Note' && $s['attach']) {
+			$body .= self::bb_attach($s['attach']);
+		}
+
+		$body .= "[/share]";
+
+		$s['title']    = self::bb_content($content,'name');
+		$s['body']     = $body;
+
+		if($act->recips && (! in_array(ACTIVITY_PUBLIC_INBOX,$act->recips)))
+			$s['item_private'] = 1;
+
+		set_iconfig($s,'activitypub','recips',$act->raw_recips);
+
+		$r = q("select created, edited from item where mid = '%s' and uid = %d limit 1",
+			dbesc($s['mid']),
+			intval($s['uid'])
+		);
+		if($r) {
+			if($s['edited'] > $r[0]['edited']) {
+				$x = item_store_update($s);
+			}
+			else {
+				return;
+			}
+		}
+		else {
+			$x = item_store($s);
+		}
+
+
+		if(is_array($x) && $x['item_id']) {
+			if($parent) {
+				if($s['owner_xchan'] === $channel['channel_hash']) {
+					// We are the owner of this conversation, so send all received comments back downstream
+					Zotlabs\Daemon\Master::Summon(array('Notifier','comment-import',$x['item_id']));
+				}
+				$r = q("select * from item where id = %d limit 1",
+					intval($x['item_id'])
+				);
+				if($r) {
+					send_status_notifications($x['item_id'],$r[0]);
+				}
+			}
+			sync_an_item($channel['channel_id'],$x['item_id']);
+		}
+
+
+	}
+
+	static function like_note($channel,$observer_hash,$act) {
+
+		$s = [];
+
+		$parent = $act->obj['id'];
+	
+		if($act->type === 'Like')
+			$s['verb'] = ACTIVITY_LIKE;
+		if($act->type === 'Dislike')
+			$s['verb'] = ACTIVITY_DISLIKE;
+
+		if(! $parent)
+			return;
+
+		$r = q("select * from item where uid = %d and ( mid = '%s' or  mid = '%s' ) limit 1",
+			intval($channel['channel_id']),
+			dbesc($parent),
+			dbesc(urldecode(basename($parent)))
+		);
+
+		if(! $r) {
+			logger('parent not found.');
+			return;
+		}
+
+		xchan_query($r);
+		$parent_item = $r[0];
+
+		if($parent_item['owner_xchan'] === $channel['channel_hash']) {
+			if(! perm_is_allowed($channel['channel_id'],$observer_hash,'post_comments')) {
+				logger('no comment permission.');
+				return;
+			}
+		}
+
+		if($parent_item['mid'] === $parent_item['parent_mid']) {
+			$s['parent_mid'] = $parent_item['mid'];
+		}
+		else {
+			$s['thr_parent'] = $parent_item['mid'];
+			$s['parent_mid'] = $parent_item['parent_mid'];
+		}
+
+		$s['owner_xchan'] = $parent_item['owner_xchan'];
+		$s['author_xchan'] = $observer_hash;
+	
+		$s['aid'] = $channel['channel_account_id'];
+		$s['uid'] = $channel['channel_id'];
+		$s['mid'] = $act->id;
+
+		if(! $s['parent_mid'])
+			$s['parent_mid'] = $s['mid'];
+	
+
+		$post_type = (($parent_item['resource_type'] === 'photo') ? t('photo') : t('status'));
+
+		$links = array(array('rel' => 'alternate','type' => 'text/html', 'href' => $parent_item['plink']));
+		$objtype = (($parent_item['resource_type'] === 'photo') ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
+
+		$body = $parent_item['body'];
+
+		$z = q("select * from xchan where xchan_hash = '%s' limit 1",
+			dbesc($parent_item['author_xchan'])
+		);
+		if($z)
+			$item_author = $z[0];		
+
+		$object = json_encode(array(
+			'type'    => $post_type,
+			'id'      => $parent_item['mid'],
+			'parent'  => (($parent_item['thr_parent']) ? $parent_item['thr_parent'] : $parent_item['parent_mid']),
+			'link'    => $links,
+			'title'   => $parent_item['title'],
+			'content' => $parent_item['body'],
+			'created' => $parent_item['created'],
+			'edited'  => $parent_item['edited'],
+			'author'  => array(
+				'name'     => $item_author['xchan_name'],
+				'address'  => $item_author['xchan_addr'],
+				'guid'     => $item_author['xchan_guid'],
+				'guid_sig' => $item_author['xchan_guid_sig'],
+				'link'     => array(
+					array('rel' => 'alternate', 'type' => 'text/html', 'href' => $item_author['xchan_url']),
+					array('rel' => 'photo', 'type' => $item_author['xchan_photo_mimetype'], 'href' => $item_author['xchan_photo_m'])),
+				),
+			), JSON_UNESCAPED_SLASHES
+		);
+
+		if($act->type === 'Like')
+			$bodyverb = t('%1$s likes %2$s\'s %3$s');
+		if($act->type === 'Dislike')
+			$bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s');
+
+		$ulink = '[url=' . $item_author['xchan_url'] . ']' . $item_author['xchan_name'] . '[/url]';
+		$alink = '[url=' . $parent_item['author']['xchan_url'] . ']' . $parent_item['author']['xchan_name'] . '[/url]';
+		$plink = '[url='. z_root() . '/display/' . urlencode($act->id) . ']' . $post_type . '[/url]';
+		$s['body'] =  sprintf( $bodyverb, $ulink, $alink, $plink );
+
+		$s['app']  = t('ActivityPub');
+
+		// set the route to that of the parent so downstream hubs won't reject it.
+
+		$s['route'] = $parent_item['route'];
+		$s['item_private'] = $parent_item['item_private'];
+		$s['obj_type'] = $objtype;
+		$s['obj'] = $object;
+
+		if($act->obj['conversation']) {
+			set_iconfig($s,'ostatus','conversation',$act->obj['conversation'],1);
+		}
+
+		if($act->recips && (! in_array(ACTIVITY_PUBLIC_INBOX,$act->recips)))
+			$s['item_private'] = 1;
+
+		set_iconfig($s,'activitypub','recips',$act->raw_recips);
+
+		$result = item_store($s);
+
+		if($result['success']) {
+			// if the message isn't already being relayed, notify others
+			if(intval($parent_item['item_origin']))
+					Zotlabs\Daemon\Master::Summon(array('Notifier','comment-import',$result['item_id']));
+				sync_an_item($channel['channel_id'],$result['item_id']);
+		}
+
+		return;
+	}
+
+
+	static function bb_attach($attach) {
+
+		$ret = false;
+
+		foreach($attach as $a) {
+			if(strpos($a['type'],'image') !== false) {
+				$ret .= "\n\n" . '[img]' . $a['href'] . '[/img]';
+			}
+			if(array_key_exists('type',$a) && strpos($a['type'], 'video') === 0) {
+				$ret .= "\n\n" . '[video]' . $a['href'] . '[/video]';
+			}
+			if(array_key_exists('type',$a) && strpos($a['type'], 'audio') === 0) {
+				$ret .= "\n\n" . '[audio]' . $a['href'] . '[/audio]';
+			}
+		}
+
+		return $ret;
+	}
+
+
+
+	static function bb_content($content,$field) {
+
+		require_once('include/html2bbcode.php');
+
+		$ret = false;
+
+		if(is_array($content[$field])) {
+			foreach($content[$field] as $k => $v) {
+				$ret .= '[language=' . $k . ']' . html2bbcode($v) . '[/language]';
+			}
+		}
+		else {
+			if($field === 'bbcode' && array_key_exists('bbcode',$content)) {
+				$ret = $content[$field];
+			}
+			else {
+				$ret = html2bbcode($content[$field]);
+			}
+		}
+
+		return $ret;
+	}
+
+
+	static function get_content($act) {
+
+		$content = [];
+		if (! $act) {
+			return $content;
+		}
+
+		foreach ([ 'name', 'summary', 'content' ] as $a) {
+			if (($x = self::get_textfield($act,$a)) !== false) {
+				$content[$a] = $x;
+			}
+		}
+		if (array_key_exists('source',$act) && array_key_exists('mediaType',$act['source'])) {
+			if ($act['source']['mediaType'] === 'text/bbcode') {
+				$content['bbcode'] = purify_html($act['source']['content']);
+			}
+		}
+
+		return $content;
+	}
+
+
+	static function get_textfield($act,$field) {
+	
+		$content = false;
+
+		if(array_key_exists($field,$act) && $act[$field])
+			$content = purify_html($act[$field]);
+		elseif(array_key_exists($field . 'Map',$act) && $act[$field . 'Map']) {
+			foreach($act[$field . 'Map'] as $k => $v) {
+				$content[escape_tags($k)] = purify_html($v);
+			}
+		}
+		return $content;
+	}
+}
\ No newline at end of file
diff --git a/Zotlabs/Lib/Group.php b/Zotlabs/Lib/Group.php
new file mode 100644
index 000000000..f136a3614
--- /dev/null
+++ b/Zotlabs/Lib/Group.php
@@ -0,0 +1,405 @@
+may apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL); 
+				}
+				return true;
+			}
+
+			do {
+				$dups = false;
+				$hash = random_string(32) . str_replace(['<','>'],['.','.'], $name);
+
+				$r = q("SELECT id FROM groups WHERE hash = '%s' LIMIT 1", dbesc($hash));
+				if($r)
+					$dups = true;
+			} while($dups == true);
+
+
+			$r = q("INSERT INTO groups ( hash, uid, visible, gname )
+				VALUES( '%s', %d, %d, '%s' ) ",
+				dbesc($hash),
+				intval($uid),
+				intval($public),
+				dbesc($name)
+			);
+			$ret = $r;
+		}
+
+		Libsync::build_sync_packet($uid,null,true);
+		return $ret;
+	}
+
+
+	static function remove($uid,$name) {
+		$ret = false;
+		if(x($uid) && x($name)) {
+			$r = q("SELECT id, hash FROM groups WHERE uid = %d AND gname = '%s' LIMIT 1",
+				intval($uid),
+				dbesc($name)
+			);
+			if($r) {
+				$group_id = $r[0]['id'];
+				$group_hash = $r[0]['hash'];
+			}
+
+			if(! $group_id)
+				return false;
+
+			// remove group from default posting lists
+			$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
+			       intval($uid)
+			);
+			if($r) {
+				$user_info = $r[0];
+				$change = false;
+
+				if($user_info['channel_default_group'] == $group_hash) {
+					$user_info['channel_default_group'] = '';
+					$change = true;
+				}
+				if(strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
+					$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
+					$change = true;
+				}
+				if(strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
+					$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
+					$change = true;
+				}
+
+				if($change) {
+					q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s' 
+						WHERE channel_id = %d",
+						intval($user_info['channel_default_group']),
+						dbesc($user_info['channel_allow_gid']),
+						dbesc($user_info['channel_deny_gid']),
+						intval($uid)
+					);
+				}
+			}
+
+			// remove all members
+			$r = q("DELETE FROM group_member WHERE uid = %d AND gid = %d ",
+				intval($uid),
+				intval($group_id)
+			);
+
+			// remove group
+			$r = q("UPDATE groups SET deleted = 1 WHERE uid = %d AND gname = '%s'",
+				intval($uid),
+				dbesc($name)
+			);
+
+			$ret = $r;
+
+		}
+
+		Libsync::build_sync_packet($uid,null,true);
+
+		return $ret;
+	}
+
+
+	static function byname($uid,$name) {
+		if((! $uid) || (! strlen($name)))
+			return false;
+		$r = q("SELECT * FROM groups WHERE uid = %d AND gname = '%s' LIMIT 1",
+			intval($uid),
+			dbesc($name)
+		);
+		if($r)
+			return $r[0]['id'];
+		return false;
+	}
+
+
+	static function rec_byhash($uid,$hash) {
+		if((! $uid) || (! strlen($hash)))
+			return false;
+		$r = q("SELECT * FROM groups WHERE uid = %d AND hash = '%s' LIMIT 1",
+			intval($uid),
+			dbesc($hash)
+		);
+		if($r)
+			return $r[0];
+		return false;
+	}
+
+
+	static function member_remove($uid,$name,$member) {
+		$gid = self::byname($uid,$name);
+		if(! $gid)
+			return false;
+		if(! ( $uid && $gid && $member))
+			return false;
+		$r = q("DELETE FROM group_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
+			intval($uid),
+			intval($gid),
+			dbesc($member)
+		);
+
+		Libsync::build_sync_packet($uid,null,true);
+
+		return $r;
+	}
+
+
+	static function member_add($uid,$name,$member,$gid = 0) {
+		if(! $gid)
+			$gid = self::byname($uid,$name);
+		if((! $gid) || (! $uid) || (! $member))
+			return false;
+
+		$r = q("SELECT * FROM group_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",	
+			intval($uid),
+			intval($gid),
+			dbesc($member)
+		);
+		if($r)
+			return true;	// You might question this, but 
+				// we indicate success because the group member was in fact created
+				// -- It was just created at another time
+	 	if(! $r)
+			$r = q("INSERT INTO group_member (uid, gid, xchan)
+				VALUES( %d, %d, '%s' ) ",
+				intval($uid),
+				intval($gid),
+				dbesc($member)
+		);
+
+		Libsync::build_sync_packet($uid,null,true);
+
+		return $r;
+	}
+
+
+	static function members($gid) {
+		$ret = array();
+		if(intval($gid)) {
+			$r = q("SELECT * FROM group_member 
+				LEFT JOIN abook ON abook_xchan = group_member.xchan left join xchan on xchan_hash = abook_xchan
+				WHERE gid = %d AND abook_channel = %d and group_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
+				intval($gid),
+				intval(local_channel()),
+				intval(local_channel())
+			);
+			if($r)
+				$ret = $r;
+		}
+		return $ret;
+	}
+
+	static function members_xchan($gid) {
+		$ret = [];
+		if(intval($gid)) {
+			$r = q("SELECT xchan FROM group_member WHERE gid = %d AND uid = %d",
+				intval($gid),
+				intval(local_channel())
+			);
+			if($r) {
+				foreach($r as $rr) {
+					$ret[] = $rr['xchan'];
+				}
+			}
+		}
+		return $ret;
+	}
+
+	static function members_profile_xchan($uid,$gid) {
+		$ret = [];
+
+		if(intval($gid)) {
+			$r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
+				intval($gid),
+				intval($uid)
+			);
+			if($r) {
+				foreach($r as $rr) {
+					$ret[] = $rr['xchan'];
+				}
+			}
+		}
+		return $ret;
+	}
+
+
+
+
+	static function select($uid,$group = '') {
+	
+		$grps = [];
+		$o = '';
+
+		$r = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+			intval($uid)
+		);
+		$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
+		if($r) {
+			foreach($r as $rr) {
+				$grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
+			}
+
+		}
+		logger('select: ' . print_r($grps,true), LOGGER_DATA);
+
+		$o = replace_macros(get_markup_template('group_selection.tpl'), array(
+			'$label' => t('Add new connections to this privacy group'),
+			'$groups' => $grps 
+		));
+		return $o;
+	}
+
+
+
+
+	static function widget($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
+
+		$o = '';
+
+		if(! (local_channel() && feature_enabled(local_channel(),'groups'))) {
+			return '';
+		}
+
+		$groups = array();
+
+		$r = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
+			intval($_SESSION['uid'])
+		);
+		$member_of = array();
+		if($cid) {
+			$member_of = self::containing(local_channel(),$cid);
+		} 
+
+		if($r) {
+			foreach($r as $rr) {
+				$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
+			
+				if ($edit) {
+					$groupedit = [ 'href' => "group/".$rr['id'], 'title' => t('edit') ];
+				} 
+				else {
+					$groupedit = null;
+				}
+			
+				$groups[] = [
+					'id'		=> $rr['id'],
+					'enc_cid'   => base64url_encode($cid),
+					'cid'		=> $cid,
+					'text' 		=> $rr['gname'],
+					'selected' 	=> $selected,
+					'href'		=> (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
+					'edit'		=> $groupedit,
+					'ismember'	=> in_array($rr['id'],$member_of),
+				];
+			}
+		}
+	
+	
+		$tpl = get_markup_template("group_side.tpl");
+		$o = replace_macros($tpl, array(
+			'$title'		=> t('Privacy Groups'),
+			'$edittext'     => t('Edit group'),
+			'$createtext' 	=> t('Add privacy group'),
+			'$ungrouped'    => (($every === 'contacts') ? t('Channels not in any privacy group') : ''),
+			'$groups'		=> $groups,
+			'$add'			=> t('add'),
+		));
+		
+	
+		return $o;
+	}
+
+
+	static function expand($g) {
+		if(! (is_array($g) && count($g)))
+			return array();
+
+		$ret = [];
+		$x   = [];
+
+		// private profile linked virtual groups
+
+		foreach($g as $gv) {
+			if(substr($gv,0,3) === 'vp.') {
+				$profile_hash = substr($gv,3);
+				if($profile_hash) {
+					$r = q("select abook_xchan from abook where abook_profile = '%s'",
+						dbesc($profile_hash)
+					);
+					if($r) {
+						foreach($r as $rv) {
+							$ret[] = $rv['abook_xchan'];
+						}
+					}
+				}
+			}
+			else {
+				$x[] = $gv;
+			}
+		}								 
+
+		if($x) {
+			stringify_array_elms($x,true);
+			$groups = implode(',', $x);
+			if($groups) {
+				$r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from groups where hash in ( $groups ))");
+				if($r) {
+					foreach($r as $rr) {
+						$ret[] = $rr['xchan'];
+					}
+				}
+			}
+		}
+		return $ret;
+	}
+
+
+	static function member_of($c) {
+		$r = q("SELECT groups.gname, groups.id FROM groups LEFT JOIN group_member ON group_member.gid = groups.id WHERE group_member.xchan = '%s' AND groups.deleted = 0 ORDER BY groups.gname  ASC ",
+			dbesc($c)
+		);
+
+		return $r;
+
+	}
+
+	static function containing($uid,$c) {
+
+		$r = q("SELECT gid FROM group_member WHERE uid = %d AND group_member.xchan = '%s' ",
+			intval($uid),
+			dbesc($c)
+		);
+
+		$ret = array();
+		if($r) {
+			foreach($r as $rr)
+				$ret[] = $rr['gid'];
+		}
+	
+		return $ret;
+	}
+}
\ No newline at end of file
diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php
new file mode 100644
index 000000000..938d484b7
--- /dev/null
+++ b/Zotlabs/Lib/Libsync.php
@@ -0,0 +1,1019 @@
+ $channel['channel_address'], 'url' => z_root() ];
+
+		if(array_key_exists($uid,\App::$config) && array_key_exists('transient',\App::$config[$uid])) {
+			$settings = \App::$config[$uid]['transient'];
+			if($settings) {
+				$info['config'] = $settings;
+			}
+		}
+
+		if($channel) {
+			$info['channel'] = array();
+			foreach($channel as $k => $v) {
+
+				// filter out any joined tables like xchan
+
+				if(strpos($k,'channel_') !== 0)
+					continue;
+
+				// don't pass these elements, they should not be synchronised
+
+
+				$disallowed = [
+					'channel_id','channel_account_id','channel_primary','channel_address',
+					'channel_deleted','channel_removed','channel_system'
+				];
+
+				if(! $keychange) {
+					$disallowed[] = 'channel_prvkey';
+				}
+
+				if(in_array($k,$disallowed))
+					continue;
+
+				$info['channel'][$k] = $v;
+			}
+		}
+
+		if($groups_changed) {
+			$r = q("select hash as collection, visible, deleted, gname as name from groups where uid = %d",
+				intval($uid)
+			);
+			if($r)
+				$info['collections'] = $r;
+
+			$r = q("select groups.hash as collection, group_member.xchan as member from groups left join group_member on groups.id = group_member.gid where group_member.uid = %d",
+				intval($uid)
+			);
+			if($r)
+				$info['collection_members'] = $r;
+		}
+
+		$interval = ((get_config('system','delivery_interval') !== false)
+			? intval(get_config('system','delivery_interval')) : 2 );
+
+		logger('Packet: ' . print_r($info,true), LOGGER_DATA, LOG_DEBUG);
+
+		$total = count($synchubs);
+
+		foreach($synchubs as $hub) {
+			$hash = random_string();
+			$n = Libzot::build_packet($channel,'sync',$env_recips,json_encode($info),'red',$hub['hubloc_sitekey'],$hub['site_crypto']);
+			Queue::insert(array(
+				'hash'       => $hash,
+				'account_id' => $channel['channel_account_id'],
+				'channel_id' => $channel['channel_id'],
+				'posturl'    => $hub['hubloc_callback'],
+				'notify'     => $n,
+				'msg'        => EMPTY_STR
+			));
+
+
+			$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
+			if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',3000))) {
+				logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
+				Queue::update($hash);
+				continue;
+			}
+
+
+			\Zotlabs\Daemon\Master::Summon(array('Deliver', $hash));
+			$total = $total - 1;
+
+			if($interval && $total)
+				@time_sleep_until(microtime(true) + (float) $interval);
+		}
+	}
+
+	/**
+	 * @brief
+	 *
+	 * @param array $sender
+	 * @param array $arr
+	 * @param array $deliveries
+	 * @return array
+	 */
+
+	static function process_channel_sync_delivery($sender, $arr, $deliveries) {
+
+		require_once('include/import.php');
+
+		$result = [];
+
+		$keychange = ((array_key_exists('keychange',$arr)) ? true : false);
+
+		foreach ($deliveries as $d) {
+			$r = q("select * from channel where channel_hash = '%s' limit 1",
+				dbesc($sender)
+			);
+
+			$DR = new \Zotlabs\Lib\DReport(z_root(),$sender,$d,'sync');
+
+			if (! $r) {
+				$DR->update('recipient not found');
+				$result[] = $DR->get();
+				continue;
+			}
+
+			$channel = $r[0];
+
+			$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
+
+			$max_friends = service_class_fetch($channel['channel_id'],'total_channels');
+			$max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds');
+
+			if($channel['channel_hash'] != $sender) {
+				logger('Possible forgery. Sender ' . $sender . ' is not ' . $channel['channel_hash']);
+				$DR->update('channel mismatch');
+				$result[] = $DR->get();
+				continue;
+			}
+
+			if($keychange) {
+				self::keychange($channel,$arr);
+				continue;
+			}
+
+			// if the clone is active, so are we
+
+			if(substr($channel['channel_active'],0,10) !== substr(datetime_convert(),0,10)) {
+				q("UPDATE channel set channel_active = '%s' where channel_id = %d",
+					dbesc(datetime_convert()),
+					intval($channel['channel_id'])
+				);
+			}
+
+			if(array_key_exists('config',$arr) && is_array($arr['config']) && count($arr['config'])) {
+				foreach($arr['config'] as $cat => $k) {
+					foreach($arr['config'][$cat] as $k => $v)
+						set_pconfig($channel['channel_id'],$cat,$k,$v);
+				}
+			}
+
+			if(array_key_exists('obj',$arr) && $arr['obj'])
+				sync_objs($channel,$arr['obj']);
+
+			if(array_key_exists('likes',$arr) && $arr['likes'])
+				import_likes($channel,$arr['likes']);
+
+			if(array_key_exists('app',$arr) && $arr['app'])
+				sync_apps($channel,$arr['app']);
+	
+			if(array_key_exists('chatroom',$arr) && $arr['chatroom'])
+				sync_chatrooms($channel,$arr['chatroom']);
+
+			if(array_key_exists('conv',$arr) && $arr['conv'])
+				import_conv($channel,$arr['conv']);
+
+			if(array_key_exists('mail',$arr) && $arr['mail'])
+				sync_mail($channel,$arr['mail']);
+	
+			if(array_key_exists('event',$arr) && $arr['event'])
+				sync_events($channel,$arr['event']);
+
+			if(array_key_exists('event_item',$arr) && $arr['event_item'])
+				sync_items($channel,$arr['event_item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
+
+			if(array_key_exists('item',$arr) && $arr['item'])
+				sync_items($channel,$arr['item'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
+	
+			// deprecated, maintaining for a few months for upward compatibility
+			// this should sync webpages, but the logic is a bit subtle
+
+			if(array_key_exists('item_id',$arr) && $arr['item_id'])
+				sync_items($channel,$arr['item_id']);
+
+			if(array_key_exists('menu',$arr) && $arr['menu'])
+				sync_menus($channel,$arr['menu']);
+	
+			if(array_key_exists('file',$arr) && $arr['file'])
+				sync_files($channel,$arr['file']);
+
+			if(array_key_exists('wiki',$arr) && $arr['wiki'])
+				sync_items($channel,$arr['wiki'],((array_key_exists('relocate',$arr)) ? $arr['relocate'] : null));
+
+			if(array_key_exists('channel',$arr) && is_array($arr['channel']) && count($arr['channel'])) {
+
+				$remote_channel = $arr['channel'];
+				$remote_channel['channel_id'] = $channel['channel_id'];
+
+				if(array_key_exists('channel_pageflags',$arr['channel']) && intval($arr['channel']['channel_pageflags'])) {
+
+					// Several pageflags are site-specific and cannot be sync'd.
+					// Only allow those bits which are shareable from the remote and then 
+					// logically OR with the local flags
+
+					$arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] & (PAGE_HIDDEN|PAGE_AUTOCONNECT|PAGE_APPLICATION|PAGE_PREMIUM|PAGE_ADULT);
+					$arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] | $channel['channel_pageflags'];
+
+				}
+
+				$disallowed = [
+					'channel_id',        'channel_account_id',  'channel_primary',   'channel_prvkey',
+					'channel_address',   'channel_notifyflags', 'channel_removed',   'channel_deleted',
+					'channel_system',    'channel_r_stream',    'channel_r_profile', 'channel_r_abook',
+					'channel_r_storage', 'channel_r_pages',     'channel_w_stream',  'channel_w_wall',
+					'channel_w_comment', 'channel_w_mail',      'channel_w_like',    'channel_w_tagwall',
+					'channel_w_chat',    'channel_w_storage',   'channel_w_pages',   'channel_a_republish',
+					'channel_a_delegate'
+				];
+
+				$clean = array();
+				foreach($arr['channel'] as $k => $v) {
+					if(in_array($k,$disallowed))
+						continue;
+					$clean[$k] = $v;
+				}
+				if(count($clean)) {
+					foreach($clean as $k => $v) {
+						$r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v)
+							. "' where channel_id = " . intval($channel['channel_id']) );
+					}
+				}
+			}
+
+			if(array_key_exists('abook',$arr) && is_array($arr['abook']) && count($arr['abook'])) {
+				$total_friends = 0;
+				$total_feeds = 0;
+
+				$r = q("select abook_id, abook_feed from abook where abook_channel = %d",
+					intval($channel['channel_id'])
+				);
+				if($r) {
+					// don't count yourself
+					$total_friends = ((count($r) > 0) ? count($r) - 1 : 0);
+					foreach($r as $rr)
+						if(intval($rr['abook_feed']))
+							$total_feeds ++;
+				}
+
+
+				$disallowed = array('abook_id','abook_account','abook_channel','abook_rating','abook_rating_text','abook_not_here');
+
+				$fields = db_columns($abook);
+
+				foreach($arr['abook'] as $abook) {
+
+					$abconfig = null;
+
+					if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig']))
+						$abconfig = $abook['abconfig'];
+
+					if(! array_key_exists('abook_blocked',$abook)) {
+						// convert from redmatrix
+						$abook['abook_blocked']     = (($abook['abook_flags'] & 0x0001) ? 1 : 0);
+						$abook['abook_ignored']     = (($abook['abook_flags'] & 0x0002) ? 1 : 0);
+						$abook['abook_hidden']      = (($abook['abook_flags'] & 0x0004) ? 1 : 0);
+						$abook['abook_archived']    = (($abook['abook_flags'] & 0x0008) ? 1 : 0);
+						$abook['abook_pending']     = (($abook['abook_flags'] & 0x0010) ? 1 : 0);
+						$abook['abook_unconnected'] = (($abook['abook_flags'] & 0x0020) ? 1 : 0);
+						$abook['abook_self']        = (($abook['abook_flags'] & 0x0080) ? 1 : 0);
+						$abook['abook_feed']        = (($abook['abook_flags'] & 0x0100) ? 1 : 0);
+					}
+
+					$clean = array();
+					if($abook['abook_xchan'] && $abook['entry_deleted']) {
+						logger('Removing abook entry for ' . $abook['abook_xchan']);
+
+						$r = q("select abook_id, abook_feed from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
+							dbesc($abook['abook_xchan']),
+							intval($channel['channel_id'])
+						);
+						if($r) {
+							contact_remove($channel['channel_id'],$r[0]['abook_id']);
+							if($total_friends)
+								$total_friends --;
+							if(intval($r[0]['abook_feed']))
+								$total_feeds --;
+						}
+						continue;
+					}
+
+					// Perform discovery if the referenced xchan hasn't ever been seen on this hub.
+					// This relies on the undocumented behaviour that red sites send xchan info with the abook
+					// and import_author_xchan will look them up on all federated networks
+
+					if($abook['abook_xchan'] && $abook['xchan_addr']) {
+						$h = Libzot::get_hublocs($abook['abook_xchan']);
+						if(! $h) {
+							$xhash = import_author_xchan(encode_item_xchan($abook));
+							if(! $xhash) {
+								logger('Import of ' . $abook['xchan_addr'] . ' failed.');
+								continue;
+							}
+						}
+					}
+
+					foreach($abook as $k => $v) {
+						if(in_array($k,$disallowed) || (strpos($k,'abook') !== 0)) {
+							continue;
+						}
+						if(! in_array($k,$fields)) {
+							continue;
+						}
+						$clean[$k] = $v;
+					}
+
+					if(! array_key_exists('abook_xchan',$clean))
+						continue;
+
+					if(array_key_exists('abook_instance',$clean) && $clean['abook_instance'] && strpos($clean['abook_instance'],z_root()) === false) {
+						$clean['abook_not_here'] = 1;
+					}
+
+
+					$r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+						dbesc($clean['abook_xchan']),
+						intval($channel['channel_id'])
+					);
+
+					// make sure we have an abook entry for this xchan on this system
+
+					if(! $r) {
+						if($max_friends !== false && $total_friends > $max_friends) {
+							logger('total_channels service class limit exceeded');
+							continue;
+						}
+						if($max_feeds !== false && intval($clean['abook_feed']) && $total_feeds > $max_feeds) {
+							logger('total_feeds service class limit exceeded');
+							continue;
+						}
+						abook_store_lowlevel(
+							[
+								'abook_xchan'   => $clean['abook_xchan'],
+								'abook_account' => $channel['channel_account_id'],
+								'abook_channel' => $channel['channel_id']
+							]
+						);
+						$total_friends ++;
+						if(intval($clean['abook_feed']))
+							$total_feeds ++;
+					}
+
+					if(count($clean)) {
+						foreach($clean as $k => $v) {
+							if($k == 'abook_dob')
+								$v = dbescdate($v);
+
+							$r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v)
+							. "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id']));
+						}
+					}
+
+					// This will set abconfig vars if the sender is using old-style fixed permissions
+					// using the raw abook record as passed to us. New-style permissions will fall through
+					// and be set using abconfig
+
+					// translate_abook_perms_inbound($channel,$abook);
+
+					if($abconfig) {
+						/// @fixme does not handle sync of del_abconfig
+						foreach($abconfig as $abc) {
+							set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']);
+						}
+					}
+				}
+			}
+
+			// sync collections (privacy groups) oh joy...
+
+			if(array_key_exists('collections',$arr) && is_array($arr['collections']) && count($arr['collections'])) {
+				$x = q("select * from groups where uid = %d",
+					intval($channel['channel_id'])
+				);
+				foreach($arr['collections'] as $cl) {
+					$found = false;
+					if($x) {
+						foreach($x as $y) {
+							if($cl['collection'] == $y['hash']) {
+								$found = true;
+								break;
+							}
+						}
+						if($found) {
+							if(($y['gname'] != $cl['name'])
+								|| ($y['visible'] != $cl['visible'])
+								|| ($y['deleted'] != $cl['deleted'])) {
+								q("update groups set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d",
+									dbesc($cl['name']),
+									intval($cl['visible']),
+									intval($cl['deleted']),
+									dbesc($cl['collection']),
+									intval($channel['channel_id'])
+								);
+							}
+							if(intval($cl['deleted']) && (! intval($y['deleted']))) {
+								q("delete from group_member where gid = %d",
+									intval($y['id'])
+								);
+							}
+						}
+					}
+					if(! $found) {
+						$r = q("INSERT INTO groups ( hash, uid, visible, deleted, gname )
+							VALUES( '%s', %d, %d, %d, '%s' ) ",
+							dbesc($cl['collection']),
+							intval($channel['channel_id']),
+							intval($cl['visible']),
+							intval($cl['deleted']),
+							dbesc($cl['name'])
+						);
+					}
+
+					// now look for any collections locally which weren't in the list we just received.
+					// They need to be removed by marking deleted and removing the members.
+					// This shouldn't happen except for clones created before this function was written.
+
+					if($x) {
+						$found_local = false;
+						foreach($x as $y) {
+							foreach($arr['collections'] as $cl) {
+								if($cl['collection'] == $y['hash']) {
+									$found_local = true;
+									break;
+								}
+							}
+							if(! $found_local) {
+								q("delete from group_member where gid = %d",
+									intval($y['id'])
+								);
+								q("update groups set deleted = 1 where id = %d and uid = %d",
+									intval($y['id']),
+									intval($channel['channel_id'])
+								);
+							}
+						}
+					}
+				}
+
+				// reload the group list with any updates
+				$x = q("select * from groups where uid = %d",
+					intval($channel['channel_id'])
+				);
+
+				// now sync the members
+
+				if(array_key_exists('collection_members', $arr)
+					&& is_array($arr['collection_members'])
+					&& count($arr['collection_members'])) {
+
+					// first sort into groups keyed by the group hash
+					$members = array();
+					foreach($arr['collection_members'] as $cm) {
+						if(! array_key_exists($cm['collection'],$members))
+							$members[$cm['collection']] = array();
+
+						$members[$cm['collection']][] = $cm['member'];
+					}
+
+					// our group list is already synchronised
+					if($x) {
+						foreach($x as $y) {
+	
+							// for each group, loop on members list we just received
+							if(isset($y['hash']) && isset($members[$y['hash']])) {
+								foreach($members[$y['hash']] as $member) {
+									$found = false;
+									$z = q("select xchan from group_member where gid = %d and uid = %d and xchan = '%s' limit 1",
+										intval($y['id']),
+										intval($channel['channel_id']),
+										dbesc($member)
+									);
+									if($z)
+										$found = true;
+	
+									// if somebody is in the group that wasn't before - add them
+	
+									if(! $found) {
+										q("INSERT INTO group_member (uid, gid, xchan)
+											VALUES( %d, %d, '%s' ) ",
+											intval($channel['channel_id']),
+											intval($y['id']),
+											dbesc($member)
+										);
+									}
+								}
+							}
+	
+							// now retrieve a list of members we have on this site
+							$m = q("select xchan from group_member where gid = %d and uid = %d",
+								intval($y['id']),
+								intval($channel['channel_id'])
+							);
+							if($m) {
+								foreach($m as $mm) {
+									// if the local existing member isn't in the list we just received - remove them
+									if(! in_array($mm['xchan'],$members[$y['hash']])) {
+										q("delete from group_member where xchan = '%s' and gid = %d and uid = %d",
+											dbesc($mm['xchan']),
+											intval($y['id']),
+											intval($channel['channel_id'])
+										);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+
+			if(array_key_exists('profile',$arr) && is_array($arr['profile']) && count($arr['profile'])) {
+
+				$disallowed = array('id','aid','uid','guid');
+
+				foreach($arr['profile'] as $profile) {
+	
+					$x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1",
+						dbesc($profile['profile_guid']),
+						intval($channel['channel_id'])
+					);
+					if(! $x) {
+						profile_store_lowlevel(
+							[
+								'aid'          => $channel['channel_account_id'],
+								'uid'          => $channel['channel_id'],
+								'profile_guid' => $profile['profile_guid'],
+							]
+						);
+	
+						$x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1",
+							dbesc($profile['profile_guid']),
+							intval($channel['channel_id'])
+						);
+						if(! $x)
+							continue;
+					}
+					$clean = array();
+					foreach($profile as $k => $v) {
+						if(in_array($k,$disallowed))
+							continue;
+
+						if($profile['is_default'] && in_array($k,['photo','thumb']))
+							continue;
+
+						if($k === 'name')
+							$clean['fullname'] = $v;
+						elseif($k === 'with')
+							$clean['partner'] = $v;
+						elseif($k === 'work')
+							$clean['employment'] = $v;
+						elseif(array_key_exists($k,$x[0]))
+							$clean[$k] = $v;
+
+						/**
+						 * @TODO
+						 * We also need to import local photos if a custom photo is selected
+						 */
+
+						if((strpos($profile['thumb'],'/photo/profile/l/') !== false) || intval($profile['is_default'])) {
+							$profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id'];
+							$profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id'];
+						}
+						else {
+							$profile['photo'] = z_root() . '/photo/' . basename($profile['photo']);
+							$profile['thumb'] = z_root() . '/photo/' . basename($profile['thumb']);
+						}
+					}
+
+					if(count($clean)) {
+						foreach($clean as $k => $v) {
+							$r = dbq("UPDATE profile set " . TQUOT . dbesc($k) . TQUOT . " = '" . dbesc($v)
+							. "' where profile_guid = '" . dbesc($profile['profile_guid'])
+							. "' and uid = " . intval($channel['channel_id']));
+						}
+					}
+				}
+			}
+
+			$addon = ['channel' => $channel, 'data' => $arr];
+			/**
+			 * @hooks process_channel_sync_delivery
+			 *   Called when accepting delivery of a 'sync packet' containing structure and table updates from a channel clone.
+			 *   * \e array \b channel
+			 *   * \e array \b data
+			 */
+			call_hooks('process_channel_sync_delivery', $addon);
+
+			$DR = new \Zotlabs\Lib\DReport(z_root(),$d,$d,'sync','channel sync delivered');
+
+			$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
+
+			$result[] = $DR->get();
+		}
+
+		return $result;
+	}
+
+	/**
+	 * @brief Synchronises locations.
+	 *
+	 * @param array $sender
+	 * @param array $arr
+	 * @param boolean $absolute (optional) default false
+	 * @return array
+	 */
+
+	static function sync_locations($sender, $arr, $absolute = false) {
+
+		$ret = array();
+
+		if($arr['locations']) {
+
+			if($absolute)
+				self::check_location_move($sender['hash'],$arr['locations']);
+
+			$xisting = q("select * from hubloc where hubloc_hash = '%s'",
+				dbesc($sender['hash'])
+			);
+
+			// See if a primary is specified
+
+			$has_primary = false;
+			foreach($arr['locations'] as $location) {
+				if($location['primary']) {
+					$has_primary = true;
+					break;
+				}
+			}
+
+			// Ensure that they have one primary hub
+
+			if(! $has_primary)
+				$arr['locations'][0]['primary'] = true;
+
+			foreach($arr['locations'] as $location) {
+				if(! Libzot::verify($location['url'],$location['url_sig'],$sender['public_key'])) {
+					logger('Unable to verify site signature for ' . $location['url']);
+					$ret['message'] .= sprintf( t('Unable to verify site signature for %s'), $location['url']) . EOL;
+					continue;
+				}
+
+				for($x = 0; $x < count($xisting); $x ++) {
+					if(($xisting[$x]['hubloc_url'] === $location['url'])
+						&& ($xisting[$x]['hubloc_sitekey'] === $location['sitekey'])) {
+						$xisting[$x]['updated'] = true;
+					}
+				}
+
+				if(! $location['sitekey']) {
+					logger('Empty hubloc sitekey. ' . print_r($location,true));
+					continue;
+				}
+
+				// Catch some malformed entries from the past which still exist
+
+				if(strpos($location['address'],'/') !== false)
+					$location['address'] = substr($location['address'],0,strpos($location['address'],'/'));
+
+				// match as many fields as possible in case anything at all changed.
+
+				$r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_id_url = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_site_id = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ",
+					dbesc($sender['hash']),
+					dbesc($sender['id']),
+					dbesc($sender['id_sig']),
+					dbesc($location['id_url']),
+					dbesc($location['url']),
+					dbesc($location['url_sig']),
+					dbesc($location['site_id']),
+					dbesc($location['host']),
+					dbesc($location['address']),
+					dbesc($location['callback']),
+					dbesc($location['sitekey'])
+				);
+				if($r) {
+					logger('Hub exists: ' . $location['url'], LOGGER_DEBUG);
+	
+					// update connection timestamp if this is the site we're talking to
+					// This only happens when called from import_xchan
+
+					$current_site = false;
+
+					$t = datetime_convert('UTC','UTC','now - 15 minutes');
+	
+					if(array_key_exists('site',$arr) && $location['url'] == $arr['site']['url']) {
+						q("update hubloc set hubloc_connected = '%s', hubloc_updated = '%s' where hubloc_id = %d and hubloc_connected < '%s'",
+							dbesc(datetime_convert()),
+							dbesc(datetime_convert()),
+							intval($r[0]['hubloc_id']),
+							dbesc($t)
+						);
+						$current_site = true;
+					}
+
+					if($current_site && intval($r[0]['hubloc_error'])) {
+						q("update hubloc set hubloc_error = 0 where hubloc_id = %d",
+							intval($r[0]['hubloc_id'])
+						);
+						if(intval($r[0]['hubloc_orphancheck'])) {
+							q("update hubloc set hubloc_orphancheck = 0 where hubloc_id = %d",
+								intval($r[0]['hubloc_id'])
+							);
+						}
+						q("update xchan set xchan_orphan = 0 where xchan_orphan = 1 and xchan_hash = '%s'",
+							dbesc($sender['hash'])
+						);
+					}
+
+					// Remove pure duplicates
+					if(count($r) > 1) {
+						for($h = 1; $h < count($r); $h ++) {
+							q("delete from hubloc where hubloc_id = %d",
+								intval($r[$h]['hubloc_id'])
+							);
+							$what .= 'duplicate_hubloc_removed ';
+							$changed = true;
+						}
+					}
+
+					if(intval($r[0]['hubloc_primary']) && (! $location['primary'])) {
+						$m = q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_id = %d",
+							dbesc(datetime_convert()),
+							intval($r[0]['hubloc_id'])
+						);
+						$r[0]['hubloc_primary'] = intval($location['primary']);
+						hubloc_change_primary($r[0]);
+						$what .= 'primary_hub ';
+						$changed = true;
+					}
+					elseif((! intval($r[0]['hubloc_primary'])) && ($location['primary'])) {
+						$m = q("update hubloc set hubloc_primary = 1, hubloc_updated = '%s' where hubloc_id = %d",
+							dbesc(datetime_convert()),
+							intval($r[0]['hubloc_id'])
+						);
+						// make sure hubloc_change_primary() has current data
+						$r[0]['hubloc_primary'] = intval($location['primary']);
+						hubloc_change_primary($r[0]);
+						$what .= 'primary_hub ';
+						$changed = true;
+					}
+					elseif($absolute) {
+						// Absolute sync - make sure the current primary is correctly reflected in the xchan
+						$pr = hubloc_change_primary($r[0]);
+						if($pr) {
+							$what .= 'xchan_primary ';
+							$changed = true;
+						}
+					}
+					if(intval($r[0]['hubloc_deleted']) && (! intval($location['deleted']))) {
+						$n = q("update hubloc set hubloc_deleted = 0, hubloc_updated = '%s' where hubloc_id = %d",
+							dbesc(datetime_convert()),
+							intval($r[0]['hubloc_id'])
+						);
+						$what .= 'undelete_hub ';
+						$changed = true;
+					}
+					elseif((! intval($r[0]['hubloc_deleted'])) && (intval($location['deleted']))) {
+						logger('deleting hubloc: ' . $r[0]['hubloc_addr']);
+						$n = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d",
+							dbesc(datetime_convert()),
+							intval($r[0]['hubloc_id'])
+						);
+						$what .= 'delete_hub ';
+						$changed = true;
+					}
+					continue;
+				}
+
+				// Existing hubs are dealt with. Now let's process any new ones.
+				// New hub claiming to be primary. Make it so by removing any existing primaries.
+
+				if(intval($location['primary'])) {
+					$r = q("update hubloc set hubloc_primary = 0, hubloc_updated = '%s' where hubloc_hash = '%s' and hubloc_primary = 1",
+						dbesc(datetime_convert()),
+						dbesc($sender['hash'])
+					);
+				}
+
+				logger('New hub: ' . $location['url']);
+
+				$r = hubloc_store_lowlevel(
+					[
+						'hubloc_guid'      => $sender['id'],
+						'hubloc_guid_sig'  => $sender['id_sig'],
+						'hubloc_id_url'    => $location['id_url'],
+						'hubloc_hash'      => $sender['hash'],
+						'hubloc_addr'      => $location['address'],
+						'hubloc_network'   => 'zot6',
+						'hubloc_primary'   => intval($location['primary']),
+						'hubloc_url'       => $location['url'],
+						'hubloc_url_sig'   => $location['url_sig'],
+						'hubloc_site_id'   => Libzot::make_xchan_hash($location['url'],$location['sitekey']),
+						'hubloc_host'      => $location['host'],
+						'hubloc_callback'  => $location['callback'],
+						'hubloc_sitekey'   => $location['sitekey'],
+						'hubloc_updated'   => datetime_convert(),
+						'hubloc_connected' => datetime_convert()
+					]
+				);
+
+				$what .= 'newhub ';
+				$changed = true;
+
+				if($location['primary']) {
+					$r = q("select * from hubloc where hubloc_addr = '%s' and hubloc_sitekey = '%s' limit 1",
+						dbesc($location['address']),
+						dbesc($location['sitekey'])
+					);
+					if($r)
+						hubloc_change_primary($r[0]);
+				}
+			}
+
+			// get rid of any hubs we have for this channel which weren't reported.
+
+			if($absolute && $xisting) {
+				foreach($xisting as $x) {
+					if(! array_key_exists('updated',$x)) {
+						logger('Deleting unreferenced hub location ' . $x['hubloc_addr']);
+						$r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d",
+							dbesc(datetime_convert()),
+							intval($x['hubloc_id'])
+						);
+						$what .= 'removed_hub ';
+						$changed = true;
+					}
+				}
+			}
+		}
+		else {
+			logger('No locations to sync!');
+		}
+
+		$ret['change_message'] = $what;
+		$ret['changed'] = $changed;
+
+		return $ret;
+	}
+
+
+	static function keychange($channel,$arr) {
+
+		// verify the keychange operation
+		if(! Libzot::verify($arr['channel']['channel_pubkey'],$arr['keychange']['new_sig'],$channel['channel_prvkey'])) {
+			logger('sync keychange: verification failed');
+			return;
+		}
+
+		$sig = Libzot::sign($channel['channel_guid'],$arr['channel']['channel_prvkey']);
+		$hash = Libzot::make_xchan_hash($channel['channel_guid'],$arr['channel']['channel_pubkey']);
+
+
+		$r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s',
+			channel_hash = '%s' where channel_id = %d",
+			dbesc($arr['channel']['channel_prvkey']),
+			dbesc($arr['channel']['channel_pubkey']),
+			dbesc($sig),
+			dbesc($hash),
+			intval($channel['channel_id'])
+		);
+		if(! $r) {
+			logger('keychange sync: channel update failed');
+			return;
+ 		}
+
+		$r = q("select * from channel where channel_id = %d",
+			intval($channel['channel_id'])
+		);
+
+		if(! $r) {
+			logger('keychange sync: channel retrieve failed');
+			return;
+		}
+
+		$channel = $r[0];
+
+		$h = q("select * from hubloc where hubloc_hash = '%s' and hubloc_url = '%s' ",
+			dbesc($arr['keychange']['old_hash']),
+			dbesc(z_root())
+		);
+
+		if($h) {
+			foreach($h as $hv) {
+				$hv['hubloc_guid_sig'] = $sig;
+				$hv['hubloc_hash']     = $hash;
+				$hv['hubloc_url_sig']  = Libzot::sign(z_root(),$channel['channel_prvkey']);
+				hubloc_store_lowlevel($hv);
+			}
+		}
+
+		$x = q("select * from xchan where xchan_hash = '%s' ",
+			dbesc($arr['keychange']['old_hash'])
+		);
+
+		$check = q("select * from xchan where xchan_hash = '%s'",
+			dbesc($hash)
+		);
+
+		if(($x) && (! $check)) {
+			$oldxchan = $x[0];
+			foreach($x as $xv) {
+				$xv['xchan_guid_sig']  = $sig;
+				$xv['xchan_hash']      = $hash;
+				$xv['xchan_pubkey']    = $channel['channel_pubkey'];
+				xchan_store_lowlevel($xv);
+				$newxchan = $xv;
+			}
+		}
+
+		$a = q("select * from abook where abook_xchan = '%s' and abook_self = 1",
+			dbesc($arr['keychange']['old_hash'])
+		);
+
+		if($a) {
+			q("update abook set abook_xchan = '%s' where abook_id = %d",
+				dbesc($hash),
+				intval($a[0]['abook_id'])
+			);
+		}
+
+		xchan_change_key($oldxchan,$newxchan,$arr['keychange']);
+
+	}
+
+}
\ No newline at end of file
diff --git a/Zotlabs/Lib/Libzot.php b/Zotlabs/Lib/Libzot.php
new file mode 100644
index 000000000..ec9db4ce1
--- /dev/null
+++ b/Zotlabs/Lib/Libzot.php
@@ -0,0 +1,2849 @@
+ $type,
+			'encoding' => $encoding,
+			'sender'   => $channel['channel_hash'],
+			'site_id'  => self::make_xchan_hash(z_root(), get_config('system','pubkey')),
+			'version'  => System::get_zot_revision(),
+		];
+
+		if ($recipients) {
+			$data['recipients'] = $recipients;
+		}
+
+		if ($msg) {
+			$actor = channel_url($channel);
+			if ($encoding === 'activitystreams' && array_key_exists('actor',$msg) && is_string($msg['actor']) && $actor === $msg['actor']) {
+				$msg = JSalmon::sign($msg,$actor,$channel['channel_prvkey']);
+			}
+			$data['data'] = $msg;
+		}
+		else {
+			unset($data['encoding']);
+		}
+
+		logger('packet: ' . print_r($data,true), LOGGER_DATA, LOG_DEBUG);
+
+		if ($remote_key) {
+			$algorithm = self::best_algorithm($methods);
+			if ($algorithm) {
+				$data = crypto_encapsulate(json_encode($data),$remote_key, $algorithm);
+			}
+		}
+
+		return json_encode($data);
+	}
+
+
+	/**
+	 * @brief Choose best encryption function from those available on both sites.
+	 *
+	 * @param string $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.
+	 */
+
+	static function best_algorithm($methods) {
+
+		$x = [
+			'methods' => $methods,
+			'result' => ''
+		];
+
+		/**
+		 * @hooks zot_best_algorithm
+		 *   Called when negotiating crypto algorithms with remote sites.
+		 *   * \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'])
+			return $x['result'];
+
+		if($methods) {
+			$x = explode(',', $methods);
+			if($x) {
+				$y = crypto_methods();
+				if($y) {
+					foreach($y as $yv) {
+						$yv = trim($yv);
+						if(in_array($yv, $x)) {
+							return($yv);
+						}
+					}
+				}
+			}
+		}
+
+		return '';
+	}
+
+
+	/**
+	 * @brief send a zot message
+	 *
+	 * @see z_post_url()
+	 *
+	 * @param string $url
+	 * @param array $data
+	 * @param array $channel (required if using zot6 delivery)
+	 * @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), 
+				'Content-type' => 'application/x-zot+json'
+			];
+
+			$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 {
+			$h = [];
+		}
+
+		$redirects = 0;
+
+		return z_post_url($url,$data,$redirects,((empty($h)) ? [] : [ 'headers' => $h ]));
+	}
+
+
+	/**
+	 * @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.
+	 *
+	 * Friending in zot is accomplished by sending a refresh packet to a specific channel which indicates a
+	 * permission change has been made by the sender which affects the target channel. The hub controlling
+	 * the target channel does targetted discovery (a zot-finger request requesting permissions for the local
+	 * channel). These are decoded here, and if necessary and abook structure (addressbook) is created to store
+	 * the permissions assigned to this channel.
+	 *
+	 * Initially these abook structures are created with a 'pending' flag, so that no reverse permissions are
+	 * implied until this is approved by the owner channel. A channel can also auto-populate permissions in
+	 * return and send back a refresh packet of its own. This is used by forum and group communication channels
+	 * so that friending and membership in the channel's "club" is automatic.
+	 *
+	 * @param array $them => xchan structure of sender
+	 * @param array $channel => local channel structure of target recipient, required for "friending" operations
+	 * @param array $force (optional) default false
+	 *
+	 * @return boolean
+	 *   * \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);
+		if ($channel)
+			logger('channel: ' . print_r($channel,true), LOGGER_DATA, LOG_DEBUG);
+
+		$url = null;
+
+		if ($them['hubloc_id_url']) {
+			$url = $them['hubloc_id_url'];
+		}
+		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.
+
+			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",
+					dbesc($them['xchan_addr'])
+				);
+			}
+			if(! $r) {
+				$r = q("select hubloc_id_url, hubloc_primary from hubloc where hubloc_hash = '%s' order by hubloc_id desc",
+					dbesc($them['xchan_hash'])
+				);
+			}
+
+			if ($r) {
+				foreach ($r as $rr) {
+					if (intval($rr['hubloc_primary'])) {
+						$url = $rr['hubloc_id_url'];
+						$record = $rr;
+					}
+				}
+				if (! $url) {
+					$url = $r[0]['hubloc_id_url'];
+				}
+			}
+		}
+		if (! $url) {
+			logger('zot_refresh: no url');
+			return false;
+		}
+
+		$s = q("select site_dead from site where site_url = '%s' limit 1",
+			dbesc($url)
+		);
+
+		if($s && intval($s[0]['site_dead']) && (! $force)) {
+			logger('zot_refresh: site ' . $url . ' is marked dead and force flag is not set. Cancelling operation.');
+			return false;
+		}
+
+		$record = Zotfinger::exec($url,$channel);
+
+		// Check the HTTP signature
+
+		$hsig = $record['signature'];
+		if($hsig && $hsig['signer'] === $url && $hsig['header_valid'] === true && $hsig['content_valid'] === true)
+			$hsig_valid = true;
+
+		if(! $hsig_valid) {
+			logger('http signature not valid: ' . print_r($hsig,true));
+			return $result;
+		}
+
+
+		logger('zot-info: ' . print_r($record,true), LOGGER_DATA, LOG_DEBUG);
+
+		$x = self::import_xchan($record['data'], (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
+
+		if(! $x['success'])
+			return false;
+
+		if($channel && $record['data']['permissions']) {
+			$old_read_stream_perm = their_perms_contains($channel['channel_id'],$x['hash'],'view_stream');
+			set_abconfig($channel['channel_id'],$x['hash'],'system','their_perms',$record['data']['permissions']);
+
+			if(array_key_exists('profile',$record['data']) && array_key_exists('next_birthday',$record['data']['profile'])) {
+				$next_birthday = datetime_convert('UTC','UTC',$record['data']['profile']['next_birthday']);
+			}
+			else {
+				$next_birthday = NULL_DATE;
+			}
+
+			$profile_assign = get_pconfig($channel['channel_id'],'system','profile_assign','');
+
+			// Keep original perms to check if we need to notify them
+			$previous_perms = get_all_perms($channel['channel_id'],$x['hash']);
+
+			$r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
+				dbesc($x['hash']),
+				intval($channel['channel_id'])
+			);
+
+			if($r) {
+
+				// connection exists
+
+				// if the dob is the same as what we have stored (disregarding the year), keep the one
+				// we have as we may have updated the year after sending a notification; and resetting
+				// to the one we just received would cause us to create duplicated events.
+
+				if(substr($r[0]['abook_dob'],5) == substr($next_birthday,5))
+					$next_birthday = $r[0]['abook_dob'];
+
+				$y = q("update abook set abook_dob = '%s'
+					where abook_xchan = '%s' and abook_channel = %d
+					and abook_self = 0 ",
+					dbescdate($next_birthday),
+					dbesc($x['hash']),
+					intval($channel['channel_id'])
+				);
+
+				if(! $y)
+					logger('abook update failed');
+				else {
+					// if we were just granted read stream permission and didn't have it before, try to pull in some posts
+					if((! $old_read_stream_perm) && (intval($permissions['view_stream'])))
+						\Zotlabs\Daemon\Master::Summon(array('Onepoll',$r[0]['abook_id']));
+				}
+			}
+			else {
+
+				$p = \Zotlabs\Access\Permissions::connect_perms($channel['channel_id']);
+				$my_perms = \Zotlabs\Access\Permissions::serialise($p['perms']);
+
+				$automatic = $p['automatic'];
+
+				// new connection
+
+				if($my_perms) {
+					set_abconfig($channel['channel_id'],$x['hash'],'system','my_perms',$my_perms);
+				}
+
+				$closeness = get_pconfig($channel['channel_id'],'system','new_abook_closeness');
+				if($closeness === false)
+					$closeness = 80;
+
+				$y = abook_store_lowlevel(
+					[
+						'abook_account'   => intval($channel['channel_account_id']),
+						'abook_channel'   => intval($channel['channel_id']),
+						'abook_closeness' => intval($closeness),
+						'abook_xchan'     => $x['hash'],
+						'abook_profile'   => $profile_assign,
+						'abook_created'   => datetime_convert(),
+						'abook_updated'   => datetime_convert(),
+						'abook_dob'       => $next_birthday,
+						'abook_pending'   => intval(($automatic) ? 0 : 1)
+					]
+				);
+
+				if($y) {
+					logger("New introduction received for {$channel['channel_name']}");
+					$new_perms = get_all_perms($channel['channel_id'],$x['hash']);
+	
+					// 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",
+						dbesc($x['hash']),
+						intval($channel['channel_id'])
+					);
+
+					if($new_connection) {
+						if(! \Zotlabs\Access\Permissions::PermsCompare($new_perms,$previous_perms))
+							\Zotlabs\Daemon\Master::Summon(array('Notifier','permissions_create',$new_connection[0]['abook_id']));
+						Enotify::submit(
+							[
+							'type'       => NOTIFY_INTRO,
+							'from_xchan' => $x['hash'],
+							'to_xchan'   => $channel['channel_hash'],
+							'link'       => z_root() . '/connedit/' . $new_connection[0]['abook_id']
+							]
+						);
+
+						if(intval($permissions['view_stream'])) {
+							if(intval(get_pconfig($channel['channel_id'],'perm_limits','send_stream') & PERMS_PENDING)
+								|| (! intval($new_connection[0]['abook_pending'])))
+								\Zotlabs\Daemon\Master::Summon(array('Onepoll',$new_connection[0]['abook_id']));
+						}
+
+
+						// If there is a default group for this channel, add this connection to it
+						// for pending connections this will happens at acceptance time.
+
+						if(! intval($new_connection[0]['abook_pending'])) {
+							$default_group = $channel['channel_default_group'];
+							if($default_group) {
+								$g = Group::rec_byhash($channel['channel_id'],$default_group);
+								if($g)
+									Group::member_add($channel['channel_id'],'',$x['hash'],$g['id']);
+							}
+						}
+
+						unset($new_connection[0]['abook_id']);
+						unset($new_connection[0]['abook_account']);
+						unset($new_connection[0]['abook_channel']);
+						$abconfig = load_abconfig($channel['channel_id'],$new_connection['abook_xchan']);
+						if($abconfig)
+							$new_connection['abconfig'] = $abconfig;
+
+						Libsync::build_sync_packet($channel['channel_id'], array('abook' => $new_connection));
+					}
+				}
+
+			}
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * @brief Look up if channel is known and previously verified.
+	 *
+	 * A guid and a url, both signed by the sender, distinguish a known sender at a
+	 * known location.
+	 * This function looks these up to see if the channel is known and therefore
+	 * previously verified. If not, we will need to verify it.
+	 *
+	 * @param array $arr an associative array which must contain:
+	 *  * \e string \b id => id of conversant
+	 *  * \e string \b id_sig => id signed with conversant's private key
+	 *  * \e string \b location => URL of the origination hub of this communication
+	 *  * \e string \b location_sig => URL signed with conversant's private key
+	 * @param boolean $multiple (optional) default false
+	 *
+	 * @return array|null
+	 *   * null if site is blacklisted or not found
+	 *   * otherwise an array with an hubloc record
+	 */
+
+	static function gethub($arr, $multiple = false) {
+
+		if($arr['id'] && $arr['id_sig'] && $arr['location'] && $arr['location_sig']) {
+
+			if(! check_siteallowed($arr['location'])) {
+				logger('blacklisted site: ' . $arr['location']);
+				return null;
+			}
+
+			$limit = (($multiple) ? '' : ' limit 1 ');
+
+			$r = q("select hubloc.*, site.site_crypto from hubloc left join site on hubloc_url = site_url
+					where hubloc_guid = '%s' and hubloc_guid_sig = '%s'
+					and hubloc_url = '%s' and hubloc_url_sig = '%s'
+					and hubloc_site_id = '%s' $limit",
+				dbesc($arr['id']),
+				dbesc($arr['id_sig']),
+				dbesc($arr['location']),
+				dbesc($arr['location_sig']),
+				dbesc($arr['site_id'])
+			);
+			if($r) {
+				logger('Found', LOGGER_DEBUG);
+				return (($multiple) ? $r : $r[0]);
+			}
+		}
+		logger('Not found: ' . print_r($arr,true), LOGGER_DEBUG);
+
+		return false;
+	}
+
+
+
+
+	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),
+			dbesc($site_id)
+		);
+		if(! $r) {
+			return null;
+		}
+
+		if(! check_siteallowed($r[0]['hubloc_url'])) {
+			logger('blacklisted site: ' . $r[0]['hubloc_url']);
+			return null;
+		}
+
+		if(! check_channelallowed($r[0]['hubloc_hash'])) {
+			logger('blacklisted channel: ' . $r[0]['hubloc_hash']);
+			return null;
+		}
+
+		return $r[0];
+
+	}
+
+	/**
+	 * @brief Registers an unknown hub.
+	 *
+	 * A communication has been received which has an unknown (to us) sender.
+	 * Perform discovery based on our calculated hash of the sender at the
+	 * 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
+	 *
+	 * @return array An associative array with
+	 *  * \b success boolean true or false
+	 *  * \b message (optional) error string only if success is false
+	 */
+
+	static function register_hub($id) {
+
+		$id_hash = false;
+		$valid   = false;
+		$hsig_valid = false;
+
+		$result  = [ 'success' => false ];
+
+		if(! $id) {
+			return $result;
+		}
+
+		$record = Zotfinger::exec($id);
+
+		// Check the HTTP signature
+
+		$hsig = $record['signature'];
+		if($hsig['signer'] === $id && $hsig['header_valid'] === true && $hsig['content_valid'] === true) {
+			$hsig_valid = true;
+		}
+		if(! $hsig_valid) {
+			logger('http signature not valid: ' . print_r($hsig,true));
+			return $result;
+		}
+
+		$c = self::import_xchan($record['data']);
+		if($c['success']) {
+			$result['success'] = true;
+		}
+		else {
+			logger('Failure to verify zot packet');
+		}
+
+		return $result;
+	}
+
+	/**
+	 * @brief Takes an associative array of a fetch discovery packet and updates
+	 *   all internal data structures which need to be updated as a result.
+	 *
+	 * @param array $arr => json_decoded discovery packet
+	 * @param int $ud_flags
+	 *    Determines whether to create a directory update record if any changes occur, default is UPDATE_FLAGS_UPDATED
+	 *    $ud_flags = UPDATE_FLAGS_FORCED indicates a forced refresh where we unconditionally create a directory update record
+	 *      this typically occurs once a month for each channel as part of a scheduled ping to notify the directory
+	 *      that the channel still exists
+	 * @param array $ud_arr
+	 *    If set [typically by update_directory_entry()] indicates a specific update table row and more particularly
+	 *    contains a particular address (ud_addr) which needs to be updated in that table.
+	 *
+	 * @return array An associative array with:
+	 *   * \e boolean \b success boolean true or false
+	 *   * \e string \b message (optional) error string only if success is false
+	 */
+
+	static function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
+
+		/**
+		 * @hooks import_xchan
+		 *   Called when processing the result of zot_finger() to store the result
+		 *   * \e array
+		 */
+		call_hooks('import_xchan', $arr);
+
+		$ret = array('success' => false);
+		$dirmode = intval(get_config('system','directory_mode'));
+
+		$changed = false;
+		$what = '';
+
+		if(! ($arr['id'] && $arr['id_sig'])) {
+			logger('No identity information provided. ' . print_r($arr,true));
+			return $ret;
+		}
+
+		$xchan_hash = self::make_xchan_hash($arr['id'],$arr['public_key']);
+		$arr['hash'] = $xchan_hash;
+
+		$import_photos = false;
+
+		$sig_methods = ((array_key_exists('signing',$arr) && is_array($arr['signing'])) ? $arr['signing'] : [ 'sha256' ]);
+		$verified = false;
+
+		if(! self::verify($arr['id'],$arr['id_sig'],$arr['public_key'])) {
+			logger('Unable to verify channel signature for ' . $arr['address']);
+			return $ret;
+		}
+		else {
+			$verified = true;
+		}
+
+		if(! $verified) {
+			$ret['message'] = t('Unable to verify channel signature');
+			return $ret;
+		}
+
+		logger('import_xchan: ' . $xchan_hash, LOGGER_DEBUG);
+
+		$r = q("select * from xchan where xchan_hash = '%s' limit 1",
+			dbesc($xchan_hash)
+		);
+
+		if(! array_key_exists('connect_url', $arr))
+			$arr['connect_url'] = '';
+
+		if($r) {
+			if($arr['photo'] && array_key_exists('updated',$arr['photo']) && $r[0]['xchan_photo_date'] != $arr['photo']['updated']) {
+				$import_photos = true;
+			}
+
+			// if we import an entry from a site that's not ours and either or both of us is off the grid - hide the entry.
+			/** @TODO: check if we're the same directory realm, which would mean we are allowed to see it */
+
+			$dirmode = get_config('system','directory_mode');
+
+			if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) && ($arr['site']['url'] != z_root()))
+				$arr['searchable'] = false;
+
+			$hidden = (1 - intval($arr['searchable']));
+
+			$hidden_changed = $adult_changed = $deleted_changed = $pubforum_changed = 0;
+
+			if(intval($r[0]['xchan_hidden']) != (1 - intval($arr['searchable'])))
+				$hidden_changed = 1;
+			if(intval($r[0]['xchan_selfcensored']) != intval($arr['adult_content']))
+				$adult_changed = 1;
+			if(intval($r[0]['xchan_deleted']) != intval($arr['deleted']))
+				$deleted_changed = 1;
+			if(intval($r[0]['xchan_pubforum']) != intval($arr['public_forum']))
+				$pubforum_changed = 1;
+
+			if($arr['protocols']) {
+				$protocols = implode(',',$arr['protocols']);
+				if($protocols !== 'zot6') {
+					set_xconfig($xchan_hash,'system','protocols',$protocols);
+				}
+				else {
+					del_xconfig($xchan_hash,'system','protocols');
+				}
+			}
+
+			if(($r[0]['xchan_name_date'] != $arr['name_updated'])
+				|| ($r[0]['xchan_connurl'] != $arr['primary_location']['connections_url'])
+				|| ($r[0]['xchan_addr'] != $arr['primary_location']['address'])
+				|| ($r[0]['xchan_follow'] != $arr['primary_location']['follow_url'])
+				|| ($r[0]['xchan_connpage'] != $arr['connect_url'])
+				|| ($r[0]['xchan_url'] != $arr['primary_location']['url'])
+				|| $hidden_changed || $adult_changed || $deleted_changed || $pubforum_changed ) {
+				$rup = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s',
+					xchan_connpage = '%s', xchan_hidden = %d, xchan_selfcensored = %d, xchan_deleted = %d, xchan_pubforum = %d,
+					xchan_addr = '%s', xchan_url = '%s' where xchan_hash = '%s'",
+					dbesc(($arr['name']) ? escape_tags($arr['name']) : '-'),
+					dbesc($arr['name_updated']),
+					dbesc($arr['primary_location']['connections_url']),
+					dbesc($arr['primary_location']['follow_url']),
+					dbesc($arr['primary_location']['connect_url']),
+					intval(1 - intval($arr['searchable'])),
+					intval($arr['adult_content']),
+					intval($arr['deleted']),
+					intval($arr['public_forum']),
+					dbesc(escape_tags($arr['primary_location']['address'])),
+					dbesc(escape_tags($arr['primary_location']['url'])),
+					dbesc($xchan_hash)
+				);
+
+				logger('Update: existing: ' . print_r($r[0],true), LOGGER_DATA, LOG_DEBUG);
+				logger('Update: new: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
+				$what .= 'xchan ';
+				$changed = true;
+			}
+		}
+		else {
+			$import_photos = true;
+
+			if((($arr['site']['directory_mode'] === 'standalone')
+					|| ($dirmode & DIRECTORY_MODE_STANDALONE))
+					&& ($arr['site']['url'] != z_root()))
+				$arr['searchable'] = false;
+
+			$x = xchan_store_lowlevel(
+				[
+					'xchan_hash'           => $xchan_hash,
+					'xchan_guid'           => $arr['id'],
+					'xchan_guid_sig'       => $arr['id_sig'],
+					'xchan_pubkey'         => $arr['public_key'],
+					'xchan_photo_mimetype' => $arr['photo_mimetype'],
+					'xchan_photo_l'        => $arr['photo'],
+					'xchan_addr'           => escape_tags($arr['primary_location']['address']),
+					'xchan_url'            => escape_tags($arr['primary_location']['url']),
+					'xchan_connurl'        => $arr['primary_location']['connections_url'],
+					'xchan_follow'         => $arr['primary_location']['follow_url'],
+					'xchan_connpage'       => $arr['connect_url'],
+					'xchan_name'           => (($arr['name']) ? escape_tags($arr['name']) : '-'),
+					'xchan_network'        => 'zot6',
+					'xchan_photo_date'     => $arr['photo_updated'],
+					'xchan_name_date'      => $arr['name_updated'],
+					'xchan_hidden'         => intval(1 - intval($arr['searchable'])),
+					'xchan_selfcensored'   => $arr['adult_content'],
+					'xchan_deleted'        => $arr['deleted'],
+					'xchan_pubforum'       => $arr['public_forum']
+				]
+			);
+
+			$what .= 'new_xchan';
+			$changed = true;
+		}
+
+		if($import_photos) {
+
+			require_once('include/photo/photo_driver.php');
+
+			// see if this is a channel clone that's hosted locally - which we treat different from other xchans/connections
+
+			$local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1",
+				dbesc($xchan_hash)
+			);
+			if($local) {
+				$ph = z_fetch_url($arr['photo']['url'], true);
+				if($ph['success']) {
+
+					$hash = import_channel_photo($ph['body'], $arr['photo']['type'], $local[0]['channel_account_id'], $local[0]['channel_id']);
+
+					if($hash) {
+						// unless proven otherwise
+						$is_default_profile = 1;
+
+						$profile = q("select is_default from profile where aid = %d and uid = %d limit 1",
+							intval($local[0]['channel_account_id']),
+							intval($local[0]['channel_id'])
+						);
+						if($profile) {
+							if(! intval($profile[0]['is_default']))
+								$is_default_profile = 0;
+						}
+
+						// 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",	
+								intval(PHOTO_NORMAL),
+								intval(PHOTO_PROFILE),
+								dbesc($hash),
+								intval($local[0]['channel_account_id']),
+								intval($local[0]['channel_id'])
+							);
+						}
+					}
+
+					// reset the names in case they got messed up when we had a bug in this function
+					$photos = array(
+						z_root() . '/photo/profile/l/' . $local[0]['channel_id'],
+						z_root() . '/photo/profile/m/' . $local[0]['channel_id'],
+						z_root() . '/photo/profile/s/' . $local[0]['channel_id'],
+						$arr['photo_mimetype'],
+						false
+					);
+				}
+			}
+			else {
+				$photos = import_xchan_photo($arr['photo']['url'], $xchan_hash);
+			}
+			if($photos) {
+				if($photos[4]) {
+					// importing the photo failed somehow. Leave the photo_date alone so we can try again at a later date.
+					// This often happens when somebody joins the matrix with a bad cert.
+					$r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
+						where xchan_hash = '%s'",
+						dbesc($photos[0]),
+						dbesc($photos[1]),
+						dbesc($photos[2]),
+						dbesc($photos[3]),
+						dbesc($xchan_hash)
+					);
+				}
+				else {
+					$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
+						where xchan_hash = '%s'",
+						dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])),
+						dbesc($photos[0]),
+						dbesc($photos[1]),
+						dbesc($photos[2]),
+						dbesc($photos[3]),
+						dbesc($xchan_hash)
+					);
+				}
+				$what .= 'photo ';
+				$changed = true;
+			}
+		}
+
+		// what we are missing for true hub independence is for any changes in the primary hub to
+		// get reflected not only in the hublocs, but also to update the URLs and addr in the appropriate xchan
+
+		$s = Libsync::sync_locations($arr, $arr);
+
+		if($s) {
+			if($s['change_message'])
+				$what .= $s['change_message'];
+			if($s['changed'])
+				$changed = $s['changed'];
+			if($s['message'])
+				$ret['message'] .= $s['message'];
+		}
+
+		// Which entries in the update table are we interested in updating?
+
+		$address = (($ud_arr && $ud_arr['ud_addr']) ? $ud_arr['ud_addr'] : $arr['address']);
+
+
+		// Are we a directory server of some kind?
+
+		$other_realm = false;
+		$realm = get_directory_realm();
+		if(array_key_exists('site',$arr)
+			&& array_key_exists('realm',$arr['site'])
+			&& (strpos($arr['site']['realm'],$realm) === false))
+			$other_realm = true;
+
+
+		if($dirmode != DIRECTORY_MODE_NORMAL) {
+
+			// We're some kind of directory server. However we can only add directory information
+			// if the entry is in the same realm (or is a sub-realm). Sub-realms are denoted by
+			// including the parent realm in the name. e.g. 'RED_GLOBAL:foo' would allow an entry to
+			// be in directories for the local realm (foo) and also the RED_GLOBAL realm.
+
+			if(array_key_exists('profile',$arr) && is_array($arr['profile']) && (! $other_realm)) {
+				$profile_changed = Libzotdir::import_directory_profile($xchan_hash,$arr['profile'],$address,$ud_flags, 1);
+				if($profile_changed) {
+					$what .= 'profile ';
+					$changed = true;
+				}
+			}
+			else {
+				logger('Profile not available - hiding');
+				// they may have made it private
+				$r = q("delete from xprof where xprof_hash = '%s'",
+					dbesc($xchan_hash)
+				);
+				$r = q("delete from xtag where xtag_hash = '%s' and xtag_flags = 0",
+					dbesc($xchan_hash)
+				);
+			}
+		}
+
+		if(array_key_exists('site',$arr) && is_array($arr['site'])) {
+			$profile_changed = self::import_site($arr['site']);
+			if($profile_changed) {
+				$what .= 'site ';
+				$changed = true;
+			}
+		}
+
+		if(($changed) || ($ud_flags == UPDATE_FLAGS_FORCED)) {
+			$guid = random_string() . '@' . \App::get_hostname();
+			Libzotdir::update_modtime($xchan_hash,$guid,$address,$ud_flags);
+			logger('Changed: ' . $what,LOGGER_DEBUG);
+		}
+		elseif(! $ud_flags) {
+			// nothing changed but we still need to update the updates record
+			q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d) > 0 ",
+				intval(UPDATE_FLAGS_UPDATED),
+				dbesc($address),
+				intval(UPDATE_FLAGS_UPDATED)
+			);
+		}
+
+		if(! x($ret,'message')) {
+			$ret['success'] = true;
+			$ret['hash'] = $xchan_hash;
+		}
+
+		logger('Result: ' . print_r($ret,true), LOGGER_DATA, LOG_DEBUG);
+		return $ret;
+	}
+
+	/**
+	 * @brief Called immediately after sending a zot message which is using queue processing.
+	 *
+	 * Updates the queue item according to the response result and logs any information
+	 * returned to aid communications troubleshooting.
+	 *
+	 * @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
+	 */
+
+	static function process_response($hub, $arr, $outq) {
+
+		logger('remote: ' . print_r($arr,true),LOGGER_DATA);
+
+		if(! $arr['success']) {
+			logger('Failed: ' . $hub);
+			return;
+		}
+
+		$x = json_decode($arr['body'], true);
+
+		if(! $x) {
+			logger('No json from ' . $hub);
+			logger('Headers: ' . print_r($arr['header'], true), LOGGER_DATA, LOG_DEBUG);
+		}
+
+		$x = crypto_unencapsulate($x, get_config('system','prvkey'));
+		if(! is_array($x)) {
+			$x = json_decode($x,true);
+		}
+
+		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()),
+				dbesc($outq['outq_hash'])
+			);
+		}
+
+		if(array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) { 
+			foreach($x['delivery_report'] as $xx) {
+				if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) {
+					q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s','%s','%s','%s','%s' ) ",
+						dbesc($xx['message_id']),
+						dbesc($xx['location']),
+						dbesc($xx['recipient']),
+						dbesc($xx['name']),
+						dbesc($xx['status']),
+						dbesc(datetime_convert($xx['date'])),
+						dbesc($xx['sender'])
+					);
+				}
+			}
+
+			// we have a more descriptive delivery report, so discard the per hub 'queue' report.
+
+			q("delete from dreport where dreport_queue = '%s' ",
+				dbesc($outq['outq_hash'])
+			);
+		}
+
+		// update the timestamp for this site
+
+		q("update site set site_dead = 0, site_update = '%s' where site_url = '%s'",
+			dbesc(datetime_convert()),
+			dbesc(dirname($hub))
+		);
+
+		// synchronous message types are handled immediately
+		// async messages remain in the queue until processed.
+
+		if(intval($outq['outq_async']))
+			Queue::remove($outq['outq_hash'],$outq['outq_channel']);
+
+		logger('zot_process_response: ' . print_r($x,true), LOGGER_DEBUG);
+	}
+
+	/**
+	 * @brief
+	 *
+	 * We received a notification packet (in mod_post) that a message is waiting for us, and we've verified the sender.
+	 * Check if the site is using zot6 delivery and includes a verified HTTP Signature, signed content, and a 'msg' field,
+	 * and also that the signer and the sender match.
+	 * If that happens, we do not need to fetch/pickup the message - we have it already and it is verified.
+	 * Translate it into the form we need for zot_import() and import it.
+	 *
+	 * Otherwise send back a pickup message, using our message tracking ID ($arr['secret']), which we will sign with our site
+	 * private key.
+	 * The entire pickup message is encrypted with the remote site's public key.
+	 * If everything checks out on the remote end, we will receive back a packet containing one or more messages,
+	 * which will be processed and delivered before this function ultimately returns.
+	 *
+	 * @see zot_import()
+	 *
+	 * @param array $arr
+	 *     decrypted and json decoded notify packet from remote site
+	 * @return array from zot_import()
+	 */
+
+	static function fetch($arr) {
+
+		logger('zot_fetch: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
+
+		return self::import($arr);
+
+	}
+
+	/**
+	 * @brief Process incoming array of messages.
+	 *
+	 * Process an incoming array of messages which were obtained via pickup, and
+	 * import, update, delete as directed.
+	 *
+	 * The message types handled here are 'activity' (e.g. posts), and 'sync'.
+	 *
+	 * @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
+	 *   * [0] => \e string $channel_hash
+	 *   * [1] => \e string $delivery_status
+	 *   * [2] => \e string $address
+	 */
+
+	static function import($arr) {
+
+		$env = $arr;
+		$private = false;
+		$return = [];
+
+		$result = null;
+
+		logger('Notify: ' . print_r($env,true), LOGGER_DATA, LOG_DEBUG);
+
+		if(! is_array($env)) {
+			logger('decode error');
+			return;
+		}
+
+		$message_request = ((array_key_exists('message_id',$env)) ? true : false);
+		if($message_request)
+			logger('processing message request');
+
+		$has_data = array_key_exists('data',$env) && $env['data'];
+		$data = (($has_data) ? $env['data'] : false);
+		
+		$deliveries = null;
+
+		if(array_key_exists('recipients',$env) && count($env['recipients'])) {
+			logger('specific recipients');
+			logger('recipients: ' . print_r($env['recipients'],true),LOGGER_DEBUG);
+
+			$recip_arr = [];
+			foreach($env['recipients'] as $recip) {
+				$recip_arr[] =  $recip;
+			}
+
+			$r = false;
+			if($recip_arr) {
+				stringify_array_elms($recip_arr,true);
+				$recips = implode(',',$recip_arr);
+				$r = q("select channel_hash as hash from channel where channel_hash in ( " . $recips . " ) and channel_removed = 0 ");
+			}
+
+			if(! $r) {
+				logger('recips: no recipients on this site');
+				return;
+			}
+
+			// Response messages will inherit the privacy of the parent
+
+			if($env['type'] !== 'response')
+				$private = true;
+
+			$deliveries = ids_to_array($r,'hash');
+
+			// We found somebody on this site that's in the recipient list.
+		}
+		else {
+
+			logger('public post');
+
+
+			// Public post. look for any site members who are or may be accepting posts from this sender
+			// and who are allowed to see them based on the sender's permissions
+			// @fixme;
+
+			$deliveries = self::public_recips($env);
+
+
+		}
+
+		$deliveries = array_unique($deliveries);
+
+		if(! $deliveries) {
+			logger('No deliveries on this site');
+			return;
+		}
+
+
+		if($has_data) {
+
+			if(in_array($env['type'],['activity','response'])) {
+
+				if($env['encoding'] === 'zot') {
+					$arr = get_item_elements($data);
+	
+					$v = validate_item_elements($data,$arr);
+					
+					if(! $v['success']) {
+						logger('Activity rejected: ' . $v['message'] . ' ' . print_r($data,true));
+						return;
+					}
+				}
+				elseif($env['encoding'] === 'activitystreams') {
+
+					$AS = new \Zotlabs\Lib\ActivityStreams($data);
+					if(! $AS->is_valid()) {
+						logger('Activity rejected: ' . print_r($data,true));
+						return;
+					}
+					$arr = \Zotlabs\Lib\Activity::decode_note($AS);
+
+					logger($AS->debug());
+
+					$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
+						dbesc($AS->actor['id'])
+					); 
+
+					if($r) {
+						$arr['author_xchan'] = $r[0]['hubloc_hash'];
+					}
+					// @fixme (in individual delivery, change owner if needed)
+					$arr['owner_xchan'] = $env['sender'];						
+					if($private) {
+						$arr['item_private'] = true;
+					}
+					// @fixme - spoofable
+					if($AS->data['hubloc']) {
+						$arr['item_verified'] = true;
+					}
+					if($AS->data['signed_data']) {
+						IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
+					}
+
+				}
+
+				logger('Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
+				logger('Activity recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG);
+
+				$relay = (($env['type'] === 'response') ? true : false );
+
+				$result = self::process_delivery($env['sender'],$arr,$deliveries,$relay,false,$message_request);
+			}
+			elseif($env['type'] === 'sync') {
+				// $arr = get_channelsync_elements($data);
+
+				$arr = json_decode($data,true);
+
+				logger('Channel sync received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
+				logger('Channel sync recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG);
+
+				$result = Libsync::process_channel_sync_delivery($env['sender'],$arr,$deliveries);
+			}
+		}
+		if ($result) {
+			$return = array_merge($return, $result);
+		}		
+		return $return;
+	}
+
+
+	static function is_top_level($env) {
+		if($env['encoding'] === 'zot' && array_key_exists('flags',$env) && in_array('thread_parent', $env['flags'])) {
+			return true;
+		}
+		if($env['encoding'] === 'activitystreams') {
+			if(array_key_exists('inReplyTo',$env['data']) && $env['data']['inReplyTo']) {
+				return false;
+			}
+			return true;
+		}
+		return false;
+	}
+
+
+	/**
+	 * @brief
+	 *
+	 * A public message with no listed recipients can be delivered to anybody who
+	 * has PERMS_NETWORK for that type of post, PERMS_AUTHED (in-network senders are
+	 * by definition authenticated) or PERMS_SITE and is one the same site,
+	 * or PERMS_SPECIFIC and the sender is a contact who is granted permissions via
+	 * their connection permissions in the address book.
+	 * Here we take a given message and construct a list of hashes of everybody
+	 * on the site that we should try and deliver to.
+	 * Some of these will be rejected, but this gives us a place to start.
+	 *
+	 * @param array $msg
+	 * @return NULL|array
+	 */
+
+	static function public_recips($msg) {
+
+		require_once('include/channel.php');
+
+		$check_mentions = false;
+		$include_sys = false;
+
+		if($msg['type'] === 'activity') {
+			$disable_discover_tab = get_config('system','disable_discover_tab') || get_config('system','disable_discover_tab') === false;
+			if(! $disable_discover_tab)
+				$include_sys = true;
+
+			$perm = 'send_stream';
+
+			if(self::is_top_level($msg)) {
+				$check_mentions = true;
+			}
+		}
+		elseif($msg['type'] === 'mail')
+			$perm = 'post_mail';
+
+		$r = [];
+
+		$c = q("select channel_id, channel_hash from channel where channel_removed = 0");
+
+		if($c) {
+			foreach($c as $cc) {
+				if(perm_is_allowed($cc['channel_id'],$msg['sender'],$perm)) {
+					$r[] = $cc['channel_hash'];
+				}
+			}
+		}
+
+		if($include_sys) {
+			$sys = get_sys_channel();
+			if($sys)
+				$r[] = $sys['channel_hash'];
+		}
+
+
+
+		// look for any public mentions on this site
+		// They will get filtered by tgroup_check() so we don't need to check permissions now
+
+		if($check_mentions) {
+			// It's a top level post. Look at the tags. See if any of them are mentions and are on this hub.
+			if(array_path_exists('data/object/tag',$msg)) {
+				if(is_array($msg['data']['object']['tag']) && $msg['data']['object']['tag']) {
+					foreach($msg['data']['object']['tag'] as $tag) {
+						if($tag['type'] === 'Mention' && (strpos($tag['href'],z_root()) !== false)) {
+							$address = basename($tag['href']);
+							if($address) {
+								$z = q("select channel_hash as hash from channel where channel_address = '%s'
+									and channel_removed = 0 limit 1",
+									dbesc($address)
+								);
+								if($z) {
+									$r[] = $z[0]['hash'];
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		else {
+			// This is a comment. We need to find any parent with ITEM_UPLINK set. But in fact, let's just return
+			// everybody that stored a copy of the parent. This way we know we're covered. We'll check the
+			// comment permissions when we deliver them.
+
+			if(array_path_exists('data/inReplyTo',$msg)) {
+				$z = q("select owner_xchan as hash from item where parent_mid = '%s' ",
+					dbesc($msg['data']['inReplyTo'])
+				);
+				if($z) {
+					foreach($z as $zv) {
+						$r[] = $zv['hash'];
+					}
+				}
+			}
+		}
+
+		// There are probably a lot of duplicates in $r at this point. We need to filter those out.
+		// It's a bit of work since it's a multi-dimensional array
+
+		if($r) {
+			$r = array_unique($r);
+		}
+
+		logger('public_recips: ' . print_r($r,true), LOGGER_DATA, LOG_DEBUG);
+		return $r;
+	}
+
+
+	/**
+	 * @brief
+	 *
+	 * @param array $sender
+	 * @param array $arr
+	 * @param array $deliveries
+	 * @param boolean $relay
+	 * @param boolean $public (optional) default false
+	 * @param boolean $request (optional) default false
+	 * @return array
+	 */
+
+	static function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) {
+
+		$result = [];
+
+		// We've validated the sender. Now make sure that the sender is the owner or author
+
+		if(! $public) {
+			if($sender != $arr['owner_xchan'] && $sender != $arr['author_xchan']) {
+				logger("Sender $sender is not owner {$arr['owner_xchan']} or author {$arr['author_xchan']} - mid {$arr['mid']}");
+				return;
+			}
+		}
+
+		foreach($deliveries as $d) {
+
+			$local_public = $public;
+
+			$DR = new \Zotlabs\Lib\DReport(z_root(),$sender,$d,$arr['mid']);
+
+			$channel = channelx_by_hash($d);
+
+			if (! $channel) {
+				$DR->update('recipient not found');
+				$result[] = $DR->get();
+				continue;
+			}
+
+			$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
+
+			/**
+			 * We need to block normal top-level message delivery from our clones, as the delivered
+			 * message doesn't have ACL information in it as the cloned copy does. That copy
+			 * 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. 
+			 */
+
+			if($sender === $channel['channel_hash'] && $arr['author_xchan'] === $channel['channel_hash'] && $arr['mid'] === $arr['parent_mid']) {
+				$DR->update('self delivery ignored');
+				$result[] = $DR->get();
+				continue;
+			}
+
+			// allow public postings to the sys channel regardless of permissions, but not
+			// for comments travelling upstream. Wait and catch them on the way down.
+			// They may have been blocked by the owner.
+
+			if(intval($channel['channel_system']) && (! $arr['item_private']) && (! $relay)) {
+				$local_public = true;
+
+				$r = q("select xchan_selfcensored from xchan where xchan_hash = '%s' limit 1",
+					dbesc($sender['hash'])
+				);
+				// don't import sys channel posts from selfcensored authors
+				if($r && (intval($r[0]['xchan_selfcensored']))) {
+					$local_public = false;
+					continue;
+				}
+				if(! MessageFilter::evaluate($arr,get_config('system','pubstream_incl'),get_config('system','pubstream_excl'))) {
+					$local_public = false;
+					continue;
+				}
+			}
+
+			$tag_delivery = tgroup_check($channel['channel_id'],$arr);
+
+			$perm = 'send_stream';
+			if(($arr['mid'] !== $arr['parent_mid']) && ($relay))
+				$perm = 'post_comments';
+
+			// This is our own post, possibly coming from a channel clone
+
+			if($arr['owner_xchan'] == $d) {
+				$arr['item_wall'] = 1;
+			}
+			else {
+				$arr['item_wall'] = 0;
+			}
+
+			if((! perm_is_allowed($channel['channel_id'],$sender,$perm)) && (! $tag_delivery) && (! $local_public)) {
+				logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
+				$DR->update('permission denied');
+				$result[] = $DR->get();
+				continue;
+			}
+
+			if($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
+				// 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 from item where mid = '%s' and uid = %d limit 1",
+					dbesc($arr['parent_mid']),
+					intval($channel['channel_id'])
+				);
+				if(! $r) {
+					$DR->update('comment parent not found');
+					$result[] = $DR->get();
+
+					// We don't seem to have a copy of this conversation or at least the parent
+					// - so request a copy of the entire conversation to date.
+					// Don't do this if it's a relay post as we're the ones who are supposed to
+					// 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).
+					// 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((! $relay) && (! $request) && (! $local_public)
+						&& perm_is_allowed($channel['channel_id'],$sender,'send_stream')) {
+						\Zotlabs\Daemon\Master::Summon(array('Notifier', 'request', $channel['channel_id'], $sender, $arr['parent_mid']));
+					}
+					continue;
+				}
+				if($relay) {
+					// 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.
+					$arr['route'] = $r[0]['route'];
+				}
+				else {
+
+					// going downstream check that we have the same upstream provider that
+					// sent it to us originally. Ignore it if it came from another source
+					// (with potentially different permissions).
+					// only compare the last hop since it could have arrived at the last location any number of ways.
+					// Always accept empty routes and firehose items (route contains 'undefined') .
+
+					$existing_route = explode(',', $r[0]['route']);
+					$routes = count($existing_route);
+					if($routes) {
+						$last_hop = array_pop($existing_route);
+						$last_prior_route = implode(',',$existing_route);
+					}
+					else {
+						$last_hop = '';
+						$last_prior_route = '';
+					}
+
+					if(in_array('undefined',$existing_route) || $last_hop == 'undefined' || $sender == 'undefined')
+						$last_hop = '';
+
+					$current_route = (($arr['route']) ? $arr['route'] . ',' : '') . $sender;
+
+					if($last_hop && $last_hop != $sender) {
+						logger('comment route mismatch: parent route = ' . $r[0]['route'] . ' expected = ' . $current_route, LOGGER_DEBUG);
+						logger('comment route mismatch: parent msg = ' . $r[0]['id'],LOGGER_DEBUG);
+						$DR->update('comment route mismatch');
+						$result[] = $DR->get();
+						continue;
+					}
+
+					// we'll add sender onto this when we deliver it. $last_prior_route now has the previously stored route
+					// *except* for the sender which would've been the last hop before it got to us.
+
+					$arr['route'] = $last_prior_route;
+				}
+			}
+
+			$ab = q("select * from abook where abook_channel = %d and abook_xchan = '%s'",
+				intval($channel['channel_id']),
+				dbesc($arr['owner_xchan'])
+			);
+			$abook = (($ab) ? $ab[0] : null);
+
+			if(intval($arr['item_deleted'])) {
+
+				// 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 = delete_imported_item($sender,$arr,$channel['channel_id'],$relay);
+				$DR->update(($item_id) ? 'deleted' : 'delete_failed');
+				$result[] = $DR->get();
+
+				if($relay && $item_id) {
+					logger('process_delivery: invoking relay');
+					\Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id)));
+					$DR->update('relayed');
+					$result[] = $DR->get();
+				}
+
+				continue;
+			}
+
+
+			$r = q("select * from item where mid = '%s' and uid = %d limit 1",
+				dbesc($arr['mid']),
+				intval($channel['channel_id'])
+			);
+			if($r) {
+				// We already have this post.
+				$item_id = $r[0]['id'];
+
+				if(intval($r[0]['item_deleted'])) {
+					// It was deleted locally.
+					$DR->update('update ignored');
+					$result[] = $DR->get();
+
+					continue;
+				}
+				// Maybe it has been edited?
+				elseif($arr['edited'] > $r[0]['edited']) {
+					$arr['id'] = $r[0]['id'];
+					$arr['uid'] = $channel['channel_id'];
+					if(($arr['mid'] == $arr['parent_mid']) && (! post_is_importable($arr,$abook))) {
+						$DR->update('update ignored');
+						$result[] = $DR->get();
+					}
+					else {
+						$item_result = self::update_imported_item($sender,$arr,$r[0],$channel['channel_id'],$tag_delivery);
+						$DR->update('updated');
+						$result[] = $DR->get();
+						if(! $relay)
+							add_source_route($item_id,$sender);
+					}
+				}
+				else {
+					$DR->update('update ignored');
+					$result[] = $DR->get();
+
+					// We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit),
+					// and at the same time not relay any other relayable posts more than once, because to do so is very wasteful.
+					if(! intval($r[0]['item_origin']))
+						continue;
+				}
+			}
+			else {
+				$arr['aid'] = $channel['channel_account_id'];
+				$arr['uid'] = $channel['channel_id'];
+
+				// if it's a sourced post, call the post_local hooks as if it were
+				// posted locally so that crosspost connectors will be triggered.
+
+				if(check_item_source($arr['uid'], $arr)) {
+					/**
+					 * @hooks post_local
+					 *   Called when an item has been posted on this machine via mod/item.php (also via API).
+					 *   * \e array with an item
+					 */
+					call_hooks('post_local', $arr);
+				}
+
+				$item_id = 0;
+
+				if(($arr['mid'] == $arr['parent_mid']) && (! post_is_importable($arr,$abook))) {
+					$DR->update('post ignored');
+					$result[] = $DR->get();
+				}
+				else {
+					$item_result = item_store($arr);
+					if($item_result['success']) {
+						$item_id = $item_result['item_id'];
+						$parr = [
+								'item_id' => $item_id,
+								'item' => $arr,
+								'sender' => $sender,
+								'channel' => $channel
+						];
+						/**
+						 * @hooks activity_received
+						 *   Called when an activity (post, comment, like, etc.) has been received from a zot source.
+						 *   * \e int \b item_id
+						 *   * \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)
+							add_source_route($item_id,$sender);
+					}
+					$DR->update(($item_id) ? 'posted' : 'storage failed: ' . $item_result['message']);
+					$result[] = $DR->get();
+				}
+			}
+
+			// preserve conversations with which you are involved from expiration
+
+			$stored = (($item_result && $item_result['item']) ? $item_result['item'] : false);
+			if((is_array($stored)) && ($stored['id'] != $stored['parent'])
+				&& ($stored['author_xchan'] === $channel['channel_hash'])) {
+				retain_item($stored['item']['parent']);
+			}
+
+			if($relay && $item_id) {
+				logger('Invoking relay');
+				\Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id)));
+				$DR->addto_update('relayed');
+				$result[] = $DR->get();
+			}
+		}
+
+		if(! $deliveries)
+			$result[] = array('', 'no recipients', '', $arr['mid']);
+
+		logger('Local results: ' . print_r($result, true), LOGGER_DEBUG);
+
+		return $result;
+	}
+
+	/**
+	 * @brief Remove community tag.
+	 *
+	 * @param array $sender an associative array with
+	 *   * \e string \b hash a xchan_hash
+	 * @param array $arr an associative array
+	 *   * \e int \b verb
+	 *   * \e int \b obj_type
+	 *   * \e int \b mid
+	 * @param int $uid
+	 */
+
+	static function remove_community_tag($sender, $arr, $uid) {
+
+		if(! (activity_match($arr['verb'], ACTIVITY_TAG) && ($arr['obj_type'] == ACTIVITY_OBJ_TAGTERM)))
+			return;
+
+		logger('remove_community_tag: invoked');
+
+		if(! get_pconfig($uid,'system','blocktags')) {
+			logger('Permission denied.');
+			return;
+		}
+
+		$r = q("select * from item where mid = '%s' and uid = %d limit 1",
+			dbesc($arr['mid']),
+			intval($uid)
+		);
+		if(! $r) {
+			logger('No item');
+			return;
+		}
+
+		if(($sender != $r[0]['owner_xchan']) && ($sender != $r[0]['author_xchan'])) {
+			logger('Sender not authorised.');
+			return;
+		}
+
+		$i = $r[0];
+	
+		if($i['target'])
+			$i['target'] = json_decode($i['target'],true);
+		if($i['object'])
+			$i['object'] = json_decode($i['object'],true);
+
+		if(! ($i['target'] && $i['object'])) {
+			logger('No target/object');
+			return;
+		}
+
+		$message_id = $i['target']['id'];
+
+		$r = q("select id from item where mid = '%s' and uid = %d limit 1",
+			dbesc($message_id),
+			intval($uid)
+		);
+		if(! $r) {
+			logger('No parent message');
+			return;
+		}
+
+		q("delete from term where uid = %d and oid = %d and otype = %d and ttype in  ( %d, %d ) and term = '%s' and url = '%s'",
+			intval($uid),
+			intval($r[0]['id']),
+			intval(TERM_OBJ_POST),
+			intval(TERM_HASHTAG),
+			intval(TERM_COMMUNITYTAG),
+			dbesc($i['object']['title']),
+			dbesc(get_rel_link($i['object']['link'],'alternate'))
+		);
+	}
+
+	/**
+	 * @brief Updates an imported item.
+	 *
+	 * @see item_store_update()
+	 *
+	 * @param array $sender
+	 * @param array $item
+	 * @param array $orig
+	 * @param int $uid
+	 * @param boolean $tag_delivery
+	 */
+	
+	static function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) {
+
+		// If this is a comment being updated, remove any privacy information
+		// so that item_store_update will set it from the original.
+
+		if($item['mid'] !== $item['parent_mid']) {
+			unset($item['allow_cid']);
+			unset($item['allow_gid']);
+			unset($item['deny_cid']);
+			unset($item['deny_gid']);
+			unset($item['item_private']);
+		}
+
+		// we need the tag_delivery check for downstream flowing posts as the stored post
+		// may have a different owner than the one being transmitted.
+
+		if(($sender != $orig['owner_xchan'] && $sender != $orig['author_xchan']) && (! $tag_delivery)) {
+			logger('sender is not owner or author');
+			return;
+		}
+
+
+		$x = item_store_update($item);
+
+		// If we're updating an event that we've saved locally, we store the item info first
+		// because event_addtocal will parse the body to get the 'new' event details
+
+		if($orig['resource_type'] === 'event') {
+			$res = event_addtocal($orig['id'], $uid);
+			if(! $res)
+				logger('update event: failed');
+		}
+
+		if(! $x['item_id'])
+			logger('update_imported_item: failed: ' . $x['message']);
+		else
+			logger('update_imported_item');
+
+		return $x;
+	}
+
+	/**
+	 * @brief Deletes an imported item.
+	 *
+	 * @param array $sender
+	 *   * \e string \b hash a xchan_hash
+	 * @param array $item
+	 * @param int $uid
+	 * @param boolean $relay
+	 * @return boolean|int post_id
+	 */
+
+	static function delete_imported_item($sender, $item, $uid, $relay) {
+
+		logger('invoked', LOGGER_DEBUG);
+
+		$ownership_valid = false;
+		$item_found = false;
+		$post_id = 0;
+
+		$r = q("select id, author_xchan, owner_xchan, source_xchan, item_deleted from item where ( author_xchan = '%s' or owner_xchan = '%s' or source_xchan = '%s' )
+			and mid = '%s' and uid = %d limit 1",
+			dbesc($sender['hash']),
+			dbesc($sender['hash']),
+			dbesc($sender['hash']),
+			dbesc($item['mid']),
+			intval($uid)
+		);
+
+		if($r) {
+			if($r[0]['author_xchan'] === $sender || $r[0]['owner_xchan'] === $sender || $r[0]['source_xchan'] === $sender)
+				$ownership_valid = true;
+
+			$post_id = $r[0]['id'];
+			$item_found = true;
+		}
+		else {
+
+			// perhaps the item is still in transit and the delete notification got here before the actual item did. Store it with the deleted flag set.
+			// item_store() won't try to deliver any notifications or start delivery chains if this flag is set.
+			// This means we won't end up with potentially even more delivery threads trying to push this delete notification.
+			// But this will ensure that if the (undeleted) original post comes in at a later date, we'll reject it because it will have an older timestamp.
+
+			logger('delete received for non-existent item - storing item data.');
+
+			if($item['author_xchan'] === $sender || $item['owner_xchan'] === $sender || $item['source_xchan'] === $sender) {
+				$ownership_valid = true;
+				$item_result = item_store($item);
+				$post_id = $item_result['item_id'];
+			}
+		}
+
+		if($ownership_valid === false) {
+			logger('delete_imported_item: failed: ownership issue');
+			return false;
+		}
+
+		if($item_found) {
+			if(intval($r[0]['item_deleted'])) {
+				logger('delete_imported_item: item was already deleted');
+				if(! $relay)
+					return false;
+
+				// This is a bit hackish, but may have to suffice until the notification/delivery loop is optimised
+				// a bit further. We're going to strip the ITEM_ORIGIN on this item if it's a comment, because
+				// it was already deleted, and we're already relaying, and this ensures that no other process or
+				// code path downstream can relay it again (causing a loop). Since it's already gone it's not coming
+				// back, and we aren't going to (or shouldn't at any rate) delete it again in the future - so losing
+				// this information from the metadata should have no other discernible impact.
+
+				if (($r[0]['id'] != $r[0]['parent']) && intval($r[0]['item_origin'])) {
+					q("update item set item_origin = 0 where id = %d and uid = %d",
+						intval($r[0]['id']),
+						intval($r[0]['uid'])
+					);
+				}
+			}
+
+
+			// Use phased deletion to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels
+			// and then clean up after ourselves with a cron job after several days to do the delete_item_lowlevel() (DROPITEM_PHASE2).
+
+			drop_item($post_id, false, DROPITEM_PHASE1);
+			tag_deliver($uid, $post_id);
+		}
+
+		return $post_id;
+	}
+
+	static function process_mail_delivery($sender, $arr, $deliveries) {
+
+		$result = array();
+
+		if($sender != $arr['from_xchan']) {
+			logger('process_mail_delivery: sender is not mail author');
+			return;
+		}
+
+		foreach($deliveries as $d) {
+	
+			$DR = new \Zotlabs\Lib\DReport(z_root(),$sender,$d,$arr['mid']);
+
+			$r = q("select * from channel where channel_hash = '%s' limit 1",
+				dbesc($d['hash'])
+			);
+
+			if(! $r) {
+				$DR->update('recipient not found');
+				$result[] = $DR->get();
+				continue;
+			}
+
+			$channel = $r[0];
+			$DR->set_name($channel['channel_name'] . ' <' . channel_reddress($channel) . '>');
+
+
+			if(! perm_is_allowed($channel['channel_id'],$sender,'post_mail')) {
+
+				/* 
+				 * Always allow somebody to reply if you initiated the conversation. It's anti-social
+				 * and a bit rude to send a private message to somebody and block their ability to respond.
+				 * If you are being harrassed and want to put an end to it, delete the conversation.
+				 */
+
+				$return = false;
+				if($arr['parent_mid']) {
+					$return = q("select * from mail where mid = '%s' and channel_id = %d limit 1",
+						dbesc($arr['parent_mid']),
+						intval($channel['channel_id'])
+					);
+				}
+				if(! $return) {
+					logger("permission denied for mail delivery {$channel['channel_id']}");
+					$DR->update('permission denied');
+					$result[] = $DR->get();
+					continue;
+				}
+			}
+
+
+			$r = q("select id from mail where mid = '%s' and channel_id = %d limit 1",
+				dbesc($arr['mid']),
+				intval($channel['channel_id'])
+			);
+			if($r) {
+				if(intval($arr['mail_recalled'])) {
+					$x = q("delete from mail where id = %d and channel_id = %d",
+						intval($r[0]['id']),
+						intval($channel['channel_id'])
+					);
+					$DR->update('mail recalled');
+					$result[] = $DR->get();
+					logger('mail_recalled');
+				}
+				else {
+					$DR->update('duplicate mail received');
+					$result[] = $DR->get();
+					logger('duplicate mail received');
+				}
+				continue;
+			}
+			else {
+				$arr['account_id'] = $channel['channel_account_id'];
+				$arr['channel_id'] = $channel['channel_id'];
+				$item_id = mail_store($arr);
+				$DR->update('mail delivered');
+				$result[] = $DR->get();
+			}
+		}
+
+		return $result;
+	}
+
+
+	/**
+	 * @brief Processes delivery of profile.
+	 *
+	 * @see import_directory_profile()
+	 * @param array $sender an associative array
+	 *   * \e string \b hash a xchan_hash
+	 * @param array $arr
+	 * @param array $deliveries (unused)
+	 */
+
+	static function process_profile_delivery($sender, $arr, $deliveries) {
+
+		logger('process_profile_delivery', LOGGER_DEBUG);
+
+		$r = q("select xchan_addr from xchan where xchan_hash = '%s' limit 1",
+				dbesc($sender['hash'])
+		);
+		if($r) {
+			Libzotdir::import_directory_profile($sender, $arr, $r[0]['xchan_addr'], UPDATE_FLAGS_UPDATED, 0);
+		}
+	}
+
+
+	/**
+	 * @brief
+	 *
+	 * @param array $sender an associative array
+	 *   * \e string \b hash a xchan_hash
+	 * @param array $arr
+	 * @param array $deliveries (unused) deliveries is irrelevant
+	 */
+	static function process_location_delivery($sender, $arr, $deliveries) {
+
+		// deliveries is irrelevant
+		logger('process_location_delivery', LOGGER_DEBUG);
+
+		$r = q("select * from xchan where xchan_hash = '%s' limit 1",
+			dbesc($sender)
+		);
+		if($r) {
+			$xchan = [ 'id' => $r[0]['xchan_guid'], 'id_sig' => $r[0]['xchan_guid_sig'],
+				'hash' => $r[0]['xchan_hash'], 'public_key' => $r[0]['xchan_pubkey'] ];
+		}
+		if(array_key_exists('locations',$arr) && $arr['locations']) {
+			$x = Libsync::sync_locations($xchan,$arr,true);
+			logger('results: ' . print_r($x,true), LOGGER_DEBUG);
+			if($x['changed']) {
+				$guid = random_string() . '@' . App::get_hostname();
+				Libzotdir::update_modtime($sender,$r[0]['xchan_guid'],$arr['locations'][0]['address'],UPDATE_FLAGS_UPDATED);
+			}
+		}
+	}
+
+	/**
+	 * @brief Checks for a moved channel and sets the channel_moved flag.
+	 *
+	 * Currently the effect of this flag is to turn the channel into 'read-only' mode.
+	 * New content will not be processed (there was still an issue with blocking the
+	 * ability to post comments as of 10-Mar-2016).
+	 * We do not physically remove the channel at this time. The hub admin may choose
+	 * to do so, but is encouraged to allow a grace period of several days in case there
+	 * are any issues migrating content. This packet will generally be received by the
+	 * original site when the basic channel import has been processed.
+	 *
+	 * This will only be executed on the old location
+	 * if a new location is reported and there is only one location record.
+	 * The rest of the hubloc syncronisation will be handled within
+	 * sync_locations
+	 *
+	 * @param string $sender_hash A channel hash
+	 * @param array $locations
+	 */
+
+	static function check_location_move($sender_hash, $locations) {
+
+		if(! $locations)
+			return;
+
+		if(count($locations) != 1)
+			return;
+
+		$loc = $locations[0];
+
+		$r = q("select * from channel where channel_hash = '%s' limit 1",
+			dbesc($sender_hash)
+		);
+
+		if(! $r)
+			return;
+
+		if($loc['url'] !== z_root()) {
+			$x = q("update channel set channel_moved = '%s' where channel_hash = '%s' limit 1",
+				dbesc($loc['url']),
+				dbesc($sender_hash)
+			);
+
+			// federation plugins may wish to notify connections
+			// of the move on singleton networks
+
+			$arr = [
+				'channel' => $r[0],
+				'locations' => $locations
+			];
+			/**
+			 * @hooks location_move
+			 *   Called when a new location has been provided to a UNO channel (indicating a move rather than a clone).
+			 *   * \e array \b channel
+			 *   * \e array \b locations
+			 */
+			call_hooks('location_move', $arr);
+		}
+	}
+
+
+
+	/**
+	 * @brief Returns an array with all known distinct hubs for this channel.
+	 *
+	 * @see self::get_hublocs()
+	 * @param array $channel an associative array which must contain
+	 *  * \e string \b channel_hash the hash of the channel
+	 * @return array an array with associative arrays
+	 */
+
+	static function encode_locations($channel) {
+		$ret = [];
+
+		$x = self::get_hublocs($channel['channel_hash']);
+
+		if($x && count($x)) {
+			foreach($x as $hub) {
+
+				// if this is a local channel that has been deleted, the hubloc is no good - make sure it is marked deleted
+				// so that nobody tries to use it.
+
+				if(intval($channel['channel_removed']) && $hub['hubloc_url'] === z_root())
+					$hub['hubloc_deleted'] = 1;
+
+				$ret[] = [
+					'host'     => $hub['hubloc_host'],
+					'address'  => $hub['hubloc_addr'],
+					'id_url'   => $hub['hubloc_id_url'],
+					'primary'  => (intval($hub['hubloc_primary']) ? true : false),
+					'url'      => $hub['hubloc_url'],
+					'url_sig'  => $hub['hubloc_url_sig'],
+					'site_id'  => $hub['hubloc_site_id'],
+					'callback' => $hub['hubloc_callback'],
+					'sitekey'  => $hub['hubloc_sitekey'],
+					'deleted'  => (intval($hub['hubloc_deleted']) ? true : false)
+				];
+			}
+		}
+
+		return $ret;
+	}
+
+
+	/**
+	 * @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']))
+			return false;
+
+		if(! self::verify($arr['url'], $arr['site_sig'], $arr['sitekey'])) {
+			logger('Bad url_sig');
+			return false;
+		}
+
+		$update = false;
+		$exists = false;
+
+		$r = q("select * from site where site_url = '%s' limit 1",
+			dbesc($arr['url'])
+		);
+		if($r) {
+			$exists = true;
+			$siterecord = $r[0];
+		}
+
+		$site_directory = 0;
+		if($arr['directory_mode'] == 'normal')
+			$site_directory = DIRECTORY_MODE_NORMAL;
+		if($arr['directory_mode'] == 'primary')
+			$site_directory = DIRECTORY_MODE_PRIMARY;
+		if($arr['directory_mode'] == 'secondary')
+			$site_directory = DIRECTORY_MODE_SECONDARY;
+		if($arr['directory_mode'] == 'standalone')
+			$site_directory = DIRECTORY_MODE_STANDALONE;
+
+		$register_policy = 0;
+		if($arr['register_policy'] == 'closed')
+			$register_policy = REGISTER_CLOSED;
+		if($arr['register_policy'] == 'open')
+			$register_policy = REGISTER_OPEN;
+		if($arr['register_policy'] == 'approve')
+			$register_policy = REGISTER_APPROVE;
+
+		$access_policy = 0;
+		if(array_key_exists('access_policy',$arr)) {
+			if($arr['access_policy'] === 'private')
+				$access_policy = ACCESS_PRIVATE;
+			if($arr['access_policy'] === 'paid')
+				$access_policy = ACCESS_PAID;
+			if($arr['access_policy'] === 'free')
+				$access_policy = ACCESS_FREE;
+			if($arr['access_policy'] === 'tiered')
+				$access_policy = ACCESS_TIERED;
+		}
+
+		// don't let insecure sites register as public hubs
+
+		if(strpos($arr['url'],'https://') === false)
+			$access_policy = ACCESS_PRIVATE;
+
+		if($access_policy != ACCESS_PRIVATE) {
+			$x = z_fetch_url($arr['url'] . '/siteinfo.json');
+			if(! $x['success'])
+				$access_policy = ACCESS_PRIVATE;
+		}
+
+		$directory_url = htmlspecialchars($arr['directory_url'],ENT_COMPAT,'UTF-8',false);
+		$url = htmlspecialchars(strtolower($arr['url']),ENT_COMPAT,'UTF-8',false);
+		$sellpage = htmlspecialchars($arr['sellpage'],ENT_COMPAT,'UTF-8',false);
+		$site_location = htmlspecialchars($arr['location'],ENT_COMPAT,'UTF-8',false);
+		$site_realm = htmlspecialchars($arr['realm'],ENT_COMPAT,'UTF-8',false);
+		$site_project = htmlspecialchars($arr['project'],ENT_COMPAT,'UTF-8',false);
+		$site_crypto = ((array_key_exists('encryption',$arr) && is_array($arr['encryption'])) ? htmlspecialchars(implode(',',$arr['encryption']),ENT_COMPAT,'UTF-8',false) : '');
+		$site_version = ((array_key_exists('version',$arr)) ? htmlspecialchars($arr['version'],ENT_COMPAT,'UTF-8',false) : '');
+
+		// You can have one and only one primary directory per realm.
+		// Downgrade any others claiming to be primary. As they have
+		// flubbed up this badly already, don't let them be directory servers at all.
+
+		if(($site_directory === DIRECTORY_MODE_PRIMARY)
+			&& ($site_realm === get_directory_realm())
+			&& ($arr['url'] != get_directory_primary())) {
+			$site_directory = DIRECTORY_MODE_NORMAL;
+		}
+
+		$site_flags = $site_directory;
+
+		if(array_key_exists('zot',$arr)) {
+			set_sconfig($arr['url'],'system','zot_version',$arr['zot']);
+		}
+
+		if($exists) {
+			if(($siterecord['site_flags'] != $site_flags)
+				|| ($siterecord['site_access'] != $access_policy)
+				|| ($siterecord['site_directory'] != $directory_url)
+				|| ($siterecord['site_sellpage'] != $sellpage)
+				|| ($siterecord['site_location'] != $site_location)
+				|| ($siterecord['site_register'] != $register_policy)
+				|| ($siterecord['site_project'] != $site_project)
+				|| ($siterecord['site_realm'] != $site_realm)
+				|| ($siterecord['site_crypto'] != $site_crypto)
+				|| ($siterecord['site_version'] != $site_version)   ) {
+
+				$update = true;
+
+	//			logger('import_site: input: ' . print_r($arr,true));
+	//			logger('import_site: stored: ' . print_r($siterecord,true));
+
+				$r = q("update site set site_dead = 0, site_location = '%s', site_flags = %d, site_access = %d, site_directory = '%s', site_register = %d, site_update = '%s', site_sellpage = '%s', site_realm = '%s', site_type = %d, site_project = '%s', site_version = '%s', site_crypto = '%s'
+					where site_url = '%s'",
+					dbesc($site_location),
+					intval($site_flags),
+					intval($access_policy),
+					dbesc($directory_url),
+					intval($register_policy),
+					dbesc(datetime_convert()),
+					dbesc($sellpage),
+					dbesc($site_realm),
+					intval(SITE_TYPE_ZOT),
+					dbesc($site_project),
+					dbesc($site_version),
+					dbesc($site_crypto),
+					dbesc($url)
+				);
+				if(! $r) {
+					logger('Update failed. ' . print_r($arr,true));
+				}
+			}
+			else {
+				// update the timestamp to indicate we communicated with this site
+				q("update site set site_dead = 0, site_update = '%s' where site_url = '%s'",
+					dbesc(datetime_convert()),
+					dbesc($url)
+				);
+			}
+		}
+		else {
+			$update = true;
+
+			$r = site_store_lowlevel(
+				[
+					'site_location'  => $site_location,
+					'site_url'       => $url,
+					'site_access'    => intval($access_policy),
+					'site_flags'     => intval($site_flags),
+					'site_update'    => datetime_convert(),
+					'site_directory' => $directory_url,
+					'site_register'  => intval($register_policy),
+					'site_sellpage'  => $sellpage,
+					'site_realm'     => $site_realm,
+					'site_type'      => intval(SITE_TYPE_ZOT),
+					'site_project'   => $site_project,
+					'site_version'   => $site_version,
+					'site_crypto'    => $site_crypto
+				]
+			);
+
+			if(! $r) {
+				logger('Record create failed. ' . print_r($arr,true));
+			}
+		}
+
+		return $update;
+	}
+
+	/**
+	 * @brief Returns path to /rpost
+	 *
+	 * @todo We probably should make rpost discoverable.
+	 *
+	 * @param array $observer
+	 *   * \e string \b xchan_url
+	 * @return string
+	 */
+	static function get_rpost_path($observer) {
+		if(! $observer)
+			return '';
+
+		$parsed = parse_url($observer['xchan_url']);
+
+		return $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '') . '/rpost?f=';
+	}
+
+	/**
+	 * @brief
+	 *
+	 * @param array $x
+	 * @return boolean|string return false or a hash
+	 */
+
+	static function import_author_zot($x) {
+
+		// Check that we have both a hubloc and xchan record - as occasionally storage calls will fail and
+		// we may only end up with one; which results in posts with no author name or photo and are a bit
+		// of a hassle to repair. If either or both are missing, do a full discovery probe.
+
+		$hash = self::make_xchan_hash($x['id'],$x['key']);
+
+		$desturl = $x['url'];
+
+		$r1 = q("select hubloc_url, hubloc_updated, site_dead from hubloc left join site on
+			hubloc_url = site_url where hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_primary = 1 limit 1",
+			dbesc($x['id']),
+			dbesc($x['id_sig'])
+		);
+
+		$r2 = q("select xchan_hash from xchan where xchan_guid = '%s' and xchan_guid_sig = '%s' limit 1",
+			dbesc($x['id']),
+			dbesc($x['id_sig'])
+		);
+
+		$site_dead = false;
+
+		if($r1 && intval($r1[0]['site_dead'])) {
+			$site_dead = true;
+		}
+
+		// We have valid and somewhat fresh information. Always true if it is our own site.
+
+		if($r1 && $r2 && ( $r1[0]['hubloc_updated'] > datetime_convert('UTC','UTC','now - 1 week') || $r1[0]['hubloc_url'] === z_root() ) ) {
+			logger('in cache', LOGGER_DEBUG);
+			return $hash;
+		}
+
+		logger('not in cache or cache stale - probing: ' . print_r($x,true), LOGGER_DEBUG,LOG_INFO);
+
+		// The primary hub may be dead. Try to find another one associated with this identity that is
+		// still alive. If we find one, use that url for the discovery/refresh probe. Otherwise, the dead site
+		// is all we have and there is no point probing it. Just return the hash indicating we have a
+		// cached entry and the identity is valid. It's just unreachable until they bring back their
+		// server from the grave or create another clone elsewhere.
+
+		if($site_dead) {
+			logger('dead site - ignoring', LOGGER_DEBUG,LOG_INFO);
+
+			$r = q("select hubloc_id_url from hubloc left join site on hubloc_url = site_url
+				where hubloc_hash = '%s' and site_dead = 0",
+				dbesc($hash)
+			);
+			if($r) {
+				logger('found another site that is not dead: ' . $r[0]['hubloc_url'], LOGGER_DEBUG,LOG_INFO);
+				$desturl = $r[0]['hubloc_url'];
+			}
+			else {
+				return $hash;
+			}
+		}
+
+		$them = [ 'hubloc_id_url' => $desturl ];
+		if(self::refresh($them))
+			return $hash;
+
+		return false;
+	}
+
+	static function zotinfo($arr) {
+
+		$ret = [];
+
+		$zhash     = ((x($arr,'guid_hash'))  ? $arr['guid_hash']   : '');
+		$zguid     = ((x($arr,'guid'))       ? $arr['guid']        : '');
+		$zguid_sig = ((x($arr,'guid_sig'))   ? $arr['guid_sig']    : '');
+		$zaddr     = ((x($arr,'address'))    ? $arr['address']     : '');
+		$ztarget   = ((x($arr,'target_url')) ? $arr['target_url']  : '');
+		$zsig      = ((x($arr,'target_sig')) ? $arr['target_sig']  : '');
+		$zkey      = ((x($arr,'key'))        ? $arr['key']         : '');
+		$mindate   = ((x($arr,'mindate'))    ? $arr['mindate']     : '');
+		$token     = ((x($arr,'token'))      ? $arr['token']   : '');
+		$feed      = ((x($arr,'feed'))       ? intval($arr['feed']) : 0);
+
+		if($ztarget) {
+			$t = q("select * from hubloc where hubloc_id_url = '%s' limit 1",
+				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 
+				// enumerate their specific permissions
+		
+				$ztarget_hash = EMPTY_STR;
+			}
+		}
+
+
+		$r = null;
+
+		if(strlen($zhash)) {
+			$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+				where channel_hash = '%s' limit 1",
+				dbesc($zhash)
+			);
+		}
+		elseif(strlen($zguid) && strlen($zguid_sig)) {
+			$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+				where channel_guid = '%s' and channel_guid_sig = '%s' limit 1",
+				dbesc($zguid),
+				dbesc($zguid_sig)
+			);
+		}
+		elseif(strlen($zaddr)) {
+			if(strpos($zaddr,'[system]') === false) {       /* normal address lookup */
+				$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+					where ( channel_address = '%s' or xchan_addr = '%s' ) limit 1",
+					dbesc($zaddr),
+					dbesc($zaddr)
+				);
+			}
+
+			else {
+
+				/**
+				 * The special address '[system]' will return a system channel if one has been defined,
+				 * Or the first valid channel we find if there are no system channels.
+				 *
+				 * This is used by magic-auth if we have no prior communications with this site - and
+				 * returns an identity on this site which we can use to create a valid hub record so that
+				 * we can exchange signed messages. The precise identity is irrelevant. It's the hub
+				 * information that we really need at the other end - and this will return it.
+				 *
+				 */
+
+				$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+					where channel_system = 1 order by channel_id limit 1");
+				if(! $r) {
+					$r = q("select channel.*, xchan.* from channel left join xchan on channel_hash = xchan_hash
+						where channel_removed = 0 order by channel_id limit 1");
+				}
+			}
+		}
+		else {
+			$ret['message'] = 'Invalid request';
+			return($ret);
+		}
+
+		if(! $r) {
+			$ret['message'] = 'Item not found.';
+			return($ret);
+		}
+
+		$e = $r[0];
+
+		$id = $e['channel_id'];
+
+		$sys_channel     = (intval($e['channel_system'])   ? true : false);
+		$special_channel = (($e['channel_pageflags'] & PAGE_PREMIUM)  ? true : false);
+		$adult_channel   = (($e['channel_pageflags'] & PAGE_ADULT)    ? true : false);
+		$censored        = (($e['channel_pageflags'] & PAGE_CENSORED) ? true : false);
+		$searchable      = (($e['channel_pageflags'] & PAGE_HIDDEN)   ? false : true);
+		$deleted         = (intval($e['xchan_deleted']) ? true : false);
+
+		if($deleted || $censored || $sys_channel)
+			$searchable = false;
+
+		$public_forum = false;
+
+		$role = get_pconfig($e['channel_id'],'system','permissions_role');
+		if($role === 'forum' || $role === 'repository') {
+			$public_forum = true;
+		}
+		else {
+			// check if it has characteristics of a public forum based on custom permissions.
+			$m = \Zotlabs\Access\Permissions::FilledAutoperms($e['channel_id']);
+			if($m) {
+				foreach($m as $k => $v) {
+					if($k == 'tag_deliver' && intval($v) == 1)
+						$ch ++;
+					if($k == 'send_stream' && intval($v) == 0)
+						$ch ++;
+				}
+				if($ch == 2)
+					$public_forum = true;
+			}
+		}
+
+
+		//  This is for birthdays and keywords, but must check access permissions
+		$p = q("select * from profile where uid = %d and is_default = 1",
+			intval($e['channel_id'])
+		);
+
+		$profile = array();
+
+		if($p) {
+
+			if(! intval($p[0]['publish']))
+				$searchable = false;
+
+			$profile['description']   = $p[0]['pdesc'];
+			$profile['birthday']      = $p[0]['dob'];
+			if(($profile['birthday'] != '0000-00-00') && (($bd = z_birthday($p[0]['dob'],$e['channel_timezone'])) !== ''))
+				$profile['next_birthday'] = $bd;
+
+			if($age = age($p[0]['dob'],$e['channel_timezone'],''))
+				$profile['age'] = $age;
+			$profile['gender']        = $p[0]['gender'];
+			$profile['marital']       = $p[0]['marital'];
+			$profile['sexual']        = $p[0]['sexual'];
+			$profile['locale']        = $p[0]['locality'];
+			$profile['region']        = $p[0]['region'];
+			$profile['postcode']      = $p[0]['postal_code'];
+			$profile['country']       = $p[0]['country_name'];
+			$profile['about']         = $p[0]['about'];
+			$profile['homepage']      = $p[0]['homepage'];
+			$profile['hometown']      = $p[0]['hometown'];
+
+			if($p[0]['keywords']) {
+				$tags = array();
+				$k = explode(' ',$p[0]['keywords']);
+				if($k) {
+					foreach($k as $kk) {
+						if(trim($kk," \t\n\r\0\x0B,")) {
+							$tags[] = trim($kk," \t\n\r\0\x0B,");
+						}
+					}
+				}
+				if($tags)
+					$profile['keywords'] = $tags;
+			}
+		}
+
+		// Communication details
+
+		$ret['id']             = $e['xchan_guid'];
+		$ret['id_sig']         = self::sign($e['xchan_guid'], $e['channel_prvkey']);
+
+		$ret['primary_location'] = [ 
+			'address'            =>  $e['xchan_addr'],
+			'url'                =>  $e['xchan_url'],
+			'connections_url'    =>  $e['xchan_connurl'],
+			'follow_url'         =>  $e['xchan_follow'],
+		];
+
+		$ret['public_key']     = $e['xchan_pubkey'];
+		$ret['username']       = $e['channel_address'];
+		$ret['name']           = $e['xchan_name'];
+		$ret['name_updated']   = $e['xchan_name_date'];
+		$ret['photo'] = [
+			'url'     => $e['xchan_photo_l'],
+			'type'    => $e['xchan_photo_mimetype'],
+			'updated' => $e['xchan_photo_date']
+		];
+
+		$ret['channel_role'] = get_pconfig($e['channel_id'],'system','permissions_role','custom');
+
+		$ret['searchable']     = $searchable;
+		$ret['adult_content']  = $adult_channel;
+		$ret['public_forum']   = $public_forum;
+		
+		$ret['comments']       = map_scope(\Zotlabs\Access\PermissionLimits::Get($e['channel_id'],'post_comments'));
+		$ret['mail']           = map_scope(\Zotlabs\Access\PermissionLimits::Get($e['channel_id'],'post_mail'));
+
+		if($deleted)
+			$ret['deleted']        = $deleted;
+
+		if(intval($e['channel_removed']))
+			$ret['deleted_locally'] = true;
+
+		// premium or other channel desiring some contact with potential followers before connecting.
+		// This is a template - %s will be replaced with the follow_url we discover for the return channel.
+
+		if($special_channel) {
+			$ret['connect_url'] = (($e['xchan_connpage']) ? $e['xchan_connpage'] : z_root() . '/connect/' . $e['channel_address']);
+		}
+
+		// This is a template for our follow url, %s will be replaced with a webbie
+		if(! $ret['follow_url'])
+			$ret['follow_url'] = z_root() . '/follow?f=&url=%s';
+
+		$permissions = get_all_perms($e['channel_id'],$ztarget_hash,false);
+
+		if($ztarget_hash) {
+			$permissions['connected'] = false;
+			$b = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
+				dbesc($ztarget_hash),
+				intval($e['channel_id'])
+			);
+			if($b)
+				$permissions['connected'] = true;
+		}
+
+		if($permissions['view_profile'])
+			$ret['profile']  = $profile;
+
+
+		$concise_perms = [];
+		if($permissions) {
+			foreach($permissions as $k => $v) {
+				if($v) {
+					$concise_perms[] = $k;
+				}
+			}
+			$permissions = implode(',',$concise_perms);
+		}
+
+		$ret['permissions'] = $permissions;
+		$ret['permissions_for']         = $ztarget;
+
+
+		// array of (verified) hubs this channel uses
+
+		$x = self::encode_locations($e);
+		if($x)
+			$ret['locations'] = $x;
+
+		$ret['site'] = self::site_info();
+
+		call_hooks('zotinfo',$ret);
+
+		return($ret);
+
+	}
+
+
+	static function site_info() {
+
+		$signing_key = get_config('system','prvkey');
+		$sig_method  = get_config('system','signature_algorithm','sha256');
+
+		$ret = [];
+		$ret['site'] = [];
+		$ret['site']['url'] = z_root();
+		$ret['site']['site_sig'] = self::sign(z_root(), $signing_key);
+		$ret['site']['post'] = z_root() . '/zot';
+		$ret['site']['openWebAuth']  = z_root() . '/owa';
+		$ret['site']['authRedirect'] = z_root() . '/magic';
+		$ret['site']['sitekey'] = get_config('system','pubkey');
+
+		$dirmode = get_config('system','directory_mode');
+		if(($dirmode === false) || ($dirmode == DIRECTORY_MODE_NORMAL))
+			$ret['site']['directory_mode'] = 'normal';
+
+		if($dirmode == DIRECTORY_MODE_PRIMARY)
+			$ret['site']['directory_mode'] = 'primary';
+		elseif($dirmode == DIRECTORY_MODE_SECONDARY)
+			$ret['site']['directory_mode'] = 'secondary';
+		elseif($dirmode == DIRECTORY_MODE_STANDALONE)
+			$ret['site']['directory_mode'] = 'standalone';
+		if($dirmode != DIRECTORY_MODE_NORMAL)
+			$ret['site']['directory_url'] = z_root() . '/dirsearch';
+
+
+		$ret['site']['encryption'] = crypto_methods();
+		$ret['site']['zot'] = System::get_zot_revision();
+
+		// hide detailed site information if you're off the grid
+
+		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)
+				$ret['site']['register_policy'] = 'approve';
+			if($register_policy == REGISTER_OPEN)
+				$ret['site']['register_policy'] = 'open';
+
+
+			$access_policy = intval(get_config('system','access_policy'));
+
+			if($access_policy == ACCESS_PRIVATE)
+				$ret['site']['access_policy'] = 'private';
+			if($access_policy == ACCESS_PAID)
+				$ret['site']['access_policy'] = 'paid';
+			if($access_policy == ACCESS_FREE)
+				$ret['site']['access_policy'] = 'free';
+			if($access_policy == ACCESS_TIERED)
+				$ret['site']['access_policy'] = 'tiered';
+
+			$ret['site']['accounts'] = account_total();
+
+			require_once('include/channel.php');
+			$ret['site']['channels'] = channel_total();
+
+			$ret['site']['admin'] = get_config('system','admin_email');
+
+			$visible_plugins = array();
+			if(is_array(\App::$plugins) && count(\App::$plugins)) {
+				$r = q("select * from addon where hidden = 0");
+				if($r)
+					foreach($r as $rr)
+						$visible_plugins[] = $rr['aname'];
+			}
+
+			$ret['site']['plugins']    = $visible_plugins;
+			$ret['site']['sitehash']   = get_config('system','location_hash');
+			$ret['site']['sitename']   = get_config('system','sitename');
+			$ret['site']['sellpage']   = get_config('system','sellpage');
+			$ret['site']['location']   = get_config('system','site_location');
+			$ret['site']['realm']      = get_directory_realm();
+			$ret['site']['project']    = System::get_platform_name();
+			$ret['site']['version']    = System::get_project_version();
+
+		}
+
+		return $ret['site'];
+
+	}
+
+	/**
+	 * @brief
+	 *
+	 * @param array $hub
+	 * @param string $sitekey (optional, default empty)
+	 *
+	 * @return string hubloc_url
+	 */
+
+	static function update_hub_connected($hub, $site_id = '') {
+
+		if ($site_id) {
+
+			/*
+			 * This hub has now been proven to be valid.
+			 * Any hub with the same URL and a different sitekey cannot be valid.
+			 * Get rid of them (mark them deleted). There's a good chance they were re-installs.
+			 */
+
+			q("update hubloc set hubloc_deleted = 1, hubloc_error = 1 where hubloc_hash = '%s' and hubloc_url = '%s' and hubloc_site_id != '%s' ",
+				dbesc($hub['hubloc_hash']),
+				dbesc($hub['hubloc_url']),
+				dbesc($site_id)
+			);
+
+		}
+		else {
+			$site_id = $hub['hubloc_site_id'];
+		}
+
+		// $sender['sitekey'] is a new addition to the protocol to distinguish
+		// hublocs coming from re-installed sites. Older sites will not provide
+		// this field and we have to still mark them valid, since we can't tell
+		// if this hubloc has the same sitekey as the packet we received.
+		// Update our DB to show when we last communicated successfully with this hub
+		// This will allow us to prune dead hubs from using up resources
+
+		$t = datetime_convert('UTC', 'UTC', 'now - 15 minutes');
+
+		$r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d and hubloc_site_id = '%s' and hubloc_connected < '%s' ",
+			dbesc(datetime_convert()),
+			intval($hub['hubloc_id']),
+			dbesc($site_id),
+			dbesc($t)
+		);
+
+		// a dead hub came back to life - reset any tombstones we might have
+
+		if (intval($hub['hubloc_error'])) {
+			q("update hubloc set hubloc_error = 0 where hubloc_id = %d and hubloc_site_id = '%s' ",
+				intval($hub['hubloc_id']),
+				dbesc($site_id)
+			);
+			if (intval($hub['hubloc_orphancheck'])) {
+				q("update hubloc set hubloc_orphancheck = 0 where hubloc_id = %d and hubloc_site_id = '%s' ",
+					intval($hub['hubloc_id']),
+					dbesc($site_id)
+				);
+			}
+			q("update xchan set xchan_orphan = 0 where xchan_orphan = 1 and xchan_hash = '%s'",
+				dbesc($hub['hubloc_hash'])
+			);
+		}
+
+		return $hub['hubloc_url'];
+	}
+
+
+	static function sign($data,$key,$alg = 'sha256') {
+		if(! $key)
+			return 'no key';
+		$sig = '';
+		openssl_sign($data,$sig,$key,$alg);
+		return $alg . '.' . base64url_encode($sig);
+	}
+
+	static function verify($data,$sig,$key) {
+
+		$verify = 0;
+
+		$x = explode('.',$sig,2);
+
+		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); 
+			}
+		}
+		return(($verify > 0) ? true : false);
+	}
+
+
+
+	static function is_zot_request() {
+
+		$x = getBestSupportedMimeType([ 'application/x-zot+json' ]);
+		return(($x) ? true : false);
+	}
+
+}
diff --git a/Zotlabs/Lib/Libzotdir.php b/Zotlabs/Lib/Libzotdir.php
new file mode 100644
index 000000000..91d089c86
--- /dev/null
+++ b/Zotlabs/Lib/Libzotdir.php
@@ -0,0 +1,654 @@
+ $preferred ];
+		}
+		else {
+			return [];
+		}
+	}
+
+
+	/**
+	 * Directories may come and go over time. We will need to check that our
+	 * directory server is still valid occasionally, and reset to something that
+	 * is if our directory has gone offline for any reason
+	 */
+
+	static function check_upstream_directory() {
+
+		$directory = get_config('system', 'directory_server');
+
+		// it's possible there is no directory server configured and the local hub is being used.
+		// If so, default to preserving the absence of a specific server setting.
+
+		$isadir = true;
+
+		if ($directory) {
+			$j = Zotfinger::exec($directory);
+			if(array_path_exists('data/directory_mode',$j)) {
+				if ($j['data']['directory_mode'] === 'normal') {
+					$isadir = false;
+				}
+			}
+		}
+
+		if (! $isadir)
+			set_config('system', 'directory_server', '');
+	}
+
+
+	static function get_directory_setting($observer, $setting) {
+
+		if ($observer)
+			$ret = get_xconfig($observer, 'directory', $setting);
+		else
+			$ret = ((array_key_exists($setting,$_SESSION)) ? intval($_SESSION[$setting]) : false);
+
+		if($ret === false)
+			$ret = get_config('directory', $setting);
+
+
+		// 'safemode' is the default if there is no observer or no established preference. 
+
+		if($setting === 'safemode' && $ret === false)
+			$ret = 1;
+
+		if($setting === 'globaldir' && intval(get_config('system','localdir_hide')))
+			$ret = 1;
+
+		return $ret;
+	}
+
+	/**
+	 * @brief Called by the directory_sort widget.
+	 */
+	static function dir_sort_links() {
+
+		$safe_mode = 1;
+
+		$observer = get_observer_hash();
+
+		$safe_mode = self::get_directory_setting($observer, 'safemode');
+		$globaldir = self::get_directory_setting($observer, 'globaldir');
+		$pubforums = self::get_directory_setting($observer, 'pubforums');
+
+		$hide_local = intval(get_config('system','localdir_hide'));
+		if($hide_local)
+			$globaldir = 1;
+
+
+		// Build urls without order and pubforums so it's easy to tack on the changed value
+		// Probably there's an easier way to do this
+
+		$directory_sort_order = get_config('system','directory_sort_order');
+		if(! $directory_sort_order)
+			$directory_sort_order = 'date';
+
+		$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order);
+		$suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : '');
+
+		$url = 'directory?f=';
+
+		$tmp = array_merge($_GET,$_POST);
+		unset($tmp['suggest']);
+		unset($tmp['pubforums']);
+		unset($tmp['global']);
+		unset($tmp['safe']);
+		unset($tmp['q']);
+		unset($tmp['f']);
+		$forumsurl = $url . http_build_query($tmp) . $suggest;
+
+		$o = replace_macros(get_markup_template('dir_sort_links.tpl'), [
+			'$header'    => t('Directory Options'),
+			'$forumsurl' => $forumsurl,
+			'$safemode'  => array('safemode', t('Safe Mode'),$safe_mode,'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''),
+			'$pubforums' => array('pubforums', t('Public Forums Only'),$pubforums,'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&pubforums="+(this.checked ? 1 : 0)\''),
+			'$hide_local' => $hide_local,
+			'$globaldir' => array('globaldir', t('This Website Only'), 1-intval($globaldir),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''),
+		]);
+
+		return $o;
+	}
+
+	/**
+	 * @brief Checks the directory mode of this hub.
+	 *
+	 * Checks the directory mode of this hub to see if it is some form of directory server. If it is,
+	 * get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
+	 * a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB. 
+	 * In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored 
+	 * directly if the rater's signature matches.
+	 *
+	 * @param int $dirmode;
+	 */
+
+	static function sync_directories($dirmode) {
+
+		if ($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL)
+			return;
+
+		$realm = get_directory_realm();
+		if ($realm == DIRECTORY_REALM) {
+			$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d and ( site_realm = '%s' or site_realm = '') ",
+				intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
+				dbesc(z_root()),
+				intval(SITE_TYPE_ZOT),
+				dbesc($realm)
+			);
+		} 
+		else {
+			$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' and site_type = %d ",
+				intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
+				dbesc(z_root()),
+				dbesc(protect_sprintf('%' . $realm . '%')),
+				intval(SITE_TYPE_ZOT)
+			);
+		}
+
+		// If there are no directory servers, setup the fallback master
+		/** @FIXME What to do if we're in a different realm? */
+
+		if ((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) {
+
+			$x = site_store_lowlevel(
+				[
+					'site_url'       => DIRECTORY_FALLBACK_MASTER,
+					'site_flags'     => DIRECTORY_MODE_PRIMARY,
+					'site_update'    => NULL_DATE, 
+					'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch',
+					'site_realm'     => DIRECTORY_REALM,
+					'site_valid'     => 1,
+				]
+			);
+
+			$r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d ",
+				intval(DIRECTORY_MODE_PRIMARY),
+				intval(DIRECTORY_MODE_SECONDARY),
+				dbesc(z_root()),
+				intval(SITE_TYPE_ZOT)
+			);
+		}
+		if (! $r)
+			return;
+
+		foreach ($r as $rr) {
+			if (! $rr['site_directory'])
+				continue;
+
+			logger('sync directories: ' . $rr['site_directory']);
+
+			// for brand new directory servers, only load the last couple of days.
+			// It will take about a month for a new directory to obtain the full current repertoire of channels.
+			/** @FIXME Go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. */
+
+			$token = get_config('system','realm_token');
+
+			$syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
+			$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
+
+			if (! $x['success'])
+				continue;
+
+			$j = json_decode($x['body'],true);
+			if (!($j['transactions']) || ($j['ratings']))
+				continue;
+
+			q("update site set site_sync = '%s' where site_url = '%s'",
+				dbesc(datetime_convert()),
+				dbesc($rr['site_url'])
+			);
+
+			logger('sync_directories: ' . $rr['site_url'] . ': ' . print_r($j,true), LOGGER_DATA);
+
+			if (is_array($j['transactions']) && count($j['transactions'])) {
+				foreach ($j['transactions'] as $t) {
+					$r = q("select * from updates where ud_guid = '%s' limit 1",
+						dbesc($t['transaction_id'])
+					);
+					if($r)
+						continue;
+
+					$ud_flags = 0;
+					if (is_array($t['flags']) && in_array('deleted',$t['flags']))
+						$ud_flags |= UPDATE_FLAGS_DELETED;
+					if (is_array($t['flags']) && in_array('forced',$t['flags']))
+						$ud_flags |= UPDATE_FLAGS_FORCED;
+	
+					$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
+						values ( '%s', '%s', '%s', %d, '%s' ) ",
+						dbesc($t['hash']),
+						dbesc($t['transaction_id']),
+						dbesc($t['timestamp']),
+						intval($ud_flags),
+						dbesc($t['address'])
+					);
+				}
+			}
+		}
+	}
+
+
+
+	/**
+	 * @brief
+	 *
+	 * Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data.
+	 *
+	 * Ignore updating records marked as deleted.
+	 *
+	 * If successful, sets ud_last in the DB to the current datetime for this
+	 * reddress/webbie.
+	 *
+	 * @param array $ud Entry from update table
+	 */
+
+	static function update_directory_entry($ud) {
+
+		logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
+
+		if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
+			$success = false;
+
+			$href = \Zotlabs\Lib\Webfinger::zot_url(punify($url));
+			if($href) {
+				$zf = \Zotlabs\Lib\Zotfinger::exec($href);
+			}
+			if(is_array($zf) && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
+				$xc = Libzot::import_xchan($zf['data'], 0, $ud);
+			}
+			else {
+				q("update updates set ud_last = '%s' where ud_addr = '%s'",
+					dbesc(datetime_convert()),
+					dbesc($ud['ud_addr'])
+				);
+			}
+		}
+	}
+
+
+	/**
+	 * @brief Push local channel updates to a local directory server.
+	 *
+	 * This is called from include/directory.php if a profile is to be pushed to the
+	 * directory and the local hub in this case is any kind of directory server.
+	 *
+	 * @param int $uid
+	 * @param boolean $force
+	 */
+
+	static function local_dir_update($uid, $force) {
+
+	
+		logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
+
+		$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
+			intval($uid)
+		);
+
+		$profile = array();
+		$profile['encoding'] = 'zot';
+
+		if ($p) {
+			$hash = $p[0]['channel_hash'];
+
+			$profile['description'] = $p[0]['pdesc'];
+			$profile['birthday']    = $p[0]['dob'];
+			if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))  
+				$profile['age'] = $age;
+
+			$profile['gender']      = $p[0]['gender'];
+			$profile['marital']     = $p[0]['marital'];
+			$profile['sexual']      = $p[0]['sexual'];
+			$profile['locale']      = $p[0]['locality'];
+			$profile['region']      = $p[0]['region'];
+			$profile['postcode']    = $p[0]['postal_code'];
+			$profile['country']     = $p[0]['country_name'];
+			$profile['about']       = $p[0]['about'];
+			$profile['homepage']    = $p[0]['homepage'];
+			$profile['hometown']    = $p[0]['hometown'];
+
+			if ($p[0]['keywords']) {
+				$tags = array();
+				$k = explode(' ', $p[0]['keywords']);
+				if ($k)
+					foreach ($k as $kk)
+						if (trim($kk))
+							$tags[] = trim($kk);
+
+				if ($tags)
+					$profile['keywords'] = $tags;
+			}
+
+			$hidden = (1 - intval($p[0]['publish']));
+
+			logger('hidden: ' . $hidden);
+
+			$r = q("select xchan_hidden from xchan where xchan_hash = '%s' limit 1",
+				dbesc($p[0]['channel_hash'])
+			);
+
+			if(intval($r[0]['xchan_hidden']) != $hidden) {
+				$r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
+					intval($hidden),
+					dbesc($p[0]['channel_hash'])
+				);
+			}
+
+			$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
+			call_hooks('local_dir_update', $arr);
+
+			$address = channel_reddress($p[0]);
+
+			if (perm_is_allowed($uid, '', 'view_profile')) {
+				self::import_directory_profile($hash, $arr['profile'], $address, 0);
+			}
+			else {
+				// they may have made it private
+				$r = q("delete from xprof where xprof_hash = '%s'",
+					dbesc($hash)
+				);
+				$r = q("delete from xtag where xtag_hash = '%s'",
+					dbesc($hash)
+				);
+			}
+	
+		}
+
+		$ud_hash = random_string() . '@' . \App::get_hostname();
+		self::update_modtime($hash, $ud_hash, channel_reddress($p[0]),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
+	}
+
+
+
+	/**
+	 * @brief Imports a directory profile.
+	 *
+	 * @param string $hash
+	 * @param array $profile
+	 * @param string $addr
+	 * @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED
+	 * @param number $suppress_update (optional) default 0
+	 * @return boolean $updated if something changed
+	 */
+
+	static function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
+
+		logger('import_directory_profile', LOGGER_DEBUG);
+		if (! $hash)
+			return false;
+
+		$arr = array();
+
+		$arr['xprof_hash']         = $hash;
+		$arr['xprof_dob']          = (($profile['birthday'] === '0000-00-00') ? $profile['birthday'] : datetime_convert('','',$profile['birthday'],'Y-m-d')); // !!!! check this for 0000 year
+		$arr['xprof_age']          = (($profile['age'])         ? intval($profile['age']) : 0);
+		$arr['xprof_desc']         = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');	
+		$arr['xprof_gender']       = (($profile['gender'])      ? htmlspecialchars($profile['gender'],      ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_marital']      = (($profile['marital'])     ? htmlspecialchars($profile['marital'],     ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_sexual']       = (($profile['sexual'])      ? htmlspecialchars($profile['sexual'],      ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_locale']       = (($profile['locale'])      ? htmlspecialchars($profile['locale'],      ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_region']       = (($profile['region'])      ? htmlspecialchars($profile['region'],      ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_postcode']     = (($profile['postcode'])    ? htmlspecialchars($profile['postcode'],    ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_country']      = (($profile['country'])     ? htmlspecialchars($profile['country'],     ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_about']        = (($profile['about'])       ? htmlspecialchars($profile['about'],       ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_homepage']     = (($profile['homepage'])    ? htmlspecialchars($profile['homepage'],    ENT_COMPAT,'UTF-8',false) : '');
+		$arr['xprof_hometown']     = (($profile['hometown'])    ? htmlspecialchars($profile['hometown'],    ENT_COMPAT,'UTF-8',false) : '');
+
+		$clean = array();
+		if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) {
+			self::import_directory_keywords($hash,$profile['keywords']);
+			foreach ($profile['keywords'] as $kw) {
+				$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
+				$kw = trim($kw, ',');
+				$clean[] = $kw;
+			}
+		}
+
+		$arr['xprof_keywords'] = implode(' ',$clean);
+
+		// Self censored, make it so
+		// These are not translated, so the German "erwachsenen" keyword will not censor the directory profile. Only the English form - "adult".
+
+
+		if(in_arrayi('nsfw',$clean) || in_arrayi('adult',$clean)) {
+			q("update xchan set xchan_selfcensored = 1 where xchan_hash = '%s'",
+				dbesc($hash)
+			);
+		}
+
+		$r = q("select * from xprof where xprof_hash = '%s' limit 1",
+			dbesc($hash)
+		);
+
+		if ($arr['xprof_age'] > 150)
+			$arr['xprof_age'] = 150;
+		if ($arr['xprof_age'] < 0)
+			$arr['xprof_age'] = 0;
+
+		if ($r) {
+			$update = false;
+			foreach ($r[0] as $k => $v) {
+				if ((array_key_exists($k,$arr)) && ($arr[$k] != $v)) {
+					logger('import_directory_profile: update ' . $k . ' => ' . $arr[$k]);
+					$update = true;
+					break;
+				}
+			}
+			if ($update) {
+				q("update xprof set
+					xprof_desc = '%s',
+					xprof_dob = '%s',
+					xprof_age = %d,
+					xprof_gender = '%s',
+					xprof_marital = '%s',
+					xprof_sexual = '%s',
+					xprof_locale = '%s',
+					xprof_region = '%s',
+					xprof_postcode = '%s',
+					xprof_country = '%s',
+					xprof_about = '%s',
+					xprof_homepage = '%s',
+					xprof_hometown = '%s',
+					xprof_keywords = '%s'
+					where xprof_hash = '%s'",
+					dbesc($arr['xprof_desc']),
+					dbesc($arr['xprof_dob']),
+					intval($arr['xprof_age']),
+					dbesc($arr['xprof_gender']),
+					dbesc($arr['xprof_marital']),
+					dbesc($arr['xprof_sexual']),
+					dbesc($arr['xprof_locale']),
+					dbesc($arr['xprof_region']),
+					dbesc($arr['xprof_postcode']),
+					dbesc($arr['xprof_country']),
+					dbesc($arr['xprof_about']),
+					dbesc($arr['xprof_homepage']),
+					dbesc($arr['xprof_hometown']),
+					dbesc($arr['xprof_keywords']),
+					dbesc($arr['xprof_hash'])
+				);
+			}
+		} else {
+			$update = true;
+			logger('New profile');
+			q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_about, xprof_homepage, xprof_hometown, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
+				dbesc($arr['xprof_hash']),
+				dbesc($arr['xprof_desc']),
+				dbesc($arr['xprof_dob']),
+				intval($arr['xprof_age']),
+				dbesc($arr['xprof_gender']),
+				dbesc($arr['xprof_marital']),
+				dbesc($arr['xprof_sexual']),
+				dbesc($arr['xprof_locale']),
+				dbesc($arr['xprof_region']),
+				dbesc($arr['xprof_postcode']),
+				dbesc($arr['xprof_country']),
+				dbesc($arr['xprof_about']),
+				dbesc($arr['xprof_homepage']),
+				dbesc($arr['xprof_hometown']),
+				dbesc($arr['xprof_keywords'])
+			);
+		}
+
+		$d = [
+			'xprof' => $arr,
+			'profile' => $profile,
+			'update' => $update
+		];
+		/**
+		 * @hooks import_directory_profile
+		 *   Called when processing delivery of a profile structure from an external source (usually for directory storage).
+		 *   * \e array \b xprof
+		 *   * \e array \b profile
+		 *   * \e boolean \b update
+		 */
+		call_hooks('import_directory_profile', $d);
+
+		if (($d['update']) && (! $suppress_update))
+			self::update_modtime($arr['xprof_hash'],random_string() . '@' . \App::get_hostname(), $addr, $ud_flags);
+
+		return $d['update'];
+	}
+
+	/**
+	 * @brief
+	 *
+	 * @param string $hash An xtag_hash
+	 * @param array $keywords
+	 */
+
+	static function import_directory_keywords($hash, $keywords) {
+
+		$existing = array();
+		$r = q("select * from xtag where xtag_hash = '%s' and xtag_flags = 0",
+			dbesc($hash)
+		);
+
+		if($r) {
+			foreach($r as $rr)
+				$existing[] = $rr['xtag_term'];
+		}
+
+		$clean = array();
+		foreach($keywords as $kw) {
+			$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
+			$kw = trim($kw, ',');
+			$clean[] = $kw;
+		}
+
+		foreach($existing as $x) {
+			if(! in_array($x, $clean))
+				$r = q("delete from xtag where xtag_hash = '%s' and xtag_term = '%s' and xtag_flags = 0",
+					dbesc($hash),
+					dbesc($x)
+				);
+		}
+		foreach($clean as $x) {
+			if(! in_array($x, $existing)) {
+				$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', 0 )",
+					dbesc($hash),
+					dbesc($x)
+				);
+			}
+		}
+	}
+
+
+	/**
+	 * @brief
+	 *
+	 * @param string $hash
+	 * @param string $guid
+	 * @param string $addr
+	 * @param int $flags (optional) default 0
+	 */
+
+	static function update_modtime($hash, $guid, $addr, $flags = 0) {
+
+		$dirmode = intval(get_config('system', 'directory_mode'));
+
+		if($dirmode == DIRECTORY_MODE_NORMAL)
+			return;
+
+		if($flags) {
+			q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
+				dbesc($hash),
+				dbesc($guid),
+				dbesc(datetime_convert()),
+				intval($flags),
+				dbesc($addr)
+			);	
+		}
+		else {
+			q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ",
+				intval(UPDATE_FLAGS_UPDATED),
+				dbesc($addr),
+				intval(UPDATE_FLAGS_UPDATED)
+			);
+		}
+	}
+
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/Zotlabs/Lib/Queue.php b/Zotlabs/Lib/Queue.php
new file mode 100644
index 000000000..baa1da70d
--- /dev/null
+++ b/Zotlabs/Lib/Queue.php
@@ -0,0 +1,278 @@
+ $base,
+						'site_update' => datetime_convert(),
+						'site_dead'   => 0,
+						'site_type'   => intval(($outq['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN),
+						'site_crypto' => ''
+					]
+				);
+			}
+		}
+
+		$arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate);
+		call_hooks('queue_deliver',$arr);
+		if($arr['handled'])
+			return;
+
+		// "post" queue driver - used for diaspora and friendica-over-diaspora communications.
+
+		if($outq['outq_driver'] === 'post') {
+			$result = z_post_url($outq['outq_posturl'],$outq['outq_msg']);
+			if($result['success'] && $result['return_code'] < 300) {
+				logger('deliver: queue post success to ' . $outq['outq_posturl'], LOGGER_DEBUG);
+				if($base) {
+					q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ",
+						dbesc(datetime_convert()),
+						dbesc($base)
+					);
+				}
+				q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
+					dbesc('accepted for delivery'),
+					dbesc(datetime_convert()),
+					dbesc($outq['outq_hash'])
+				);
+				self::remove($outq['outq_hash']);
+
+				// server is responding - see if anything else is going to this destination and is piled up 
+				// and try to send some more. We're relying on the fact that do_delivery() results in an 
+				// immediate delivery otherwise we could get into a queue loop. 
+
+				if(! $immediate) {
+					$x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
+						dbesc($outq['outq_posturl'])
+					);
+	
+					$piled_up = array();
+					if($x) {
+						foreach($x as $xx) {
+							 $piled_up[] = $xx['outq_hash'];
+						}
+					}
+					if($piled_up) {
+						// call do_delivery() with the force flag
+						do_delivery($piled_up, true);
+					}
+				}
+			}
+			else {
+				logger('deliver: queue post returned ' . $result['return_code'] 
+					. ' from ' . $outq['outq_posturl'],LOGGER_DEBUG);
+					self::update($outq['outq_hash'],10);
+			}
+			return;
+		}
+
+		// normal zot delivery
+
+		logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
+
+
+		if($outq['outq_posturl'] === z_root() . '/zot') {
+			// local delivery
+			$zot = new \Zotlabs\Zot6\Receiver(new \Zotlabs\Zot6\Zot6Handler(),$outq['outq_notify']);
+			$result = $zot->run(true);
+			logger('returned_json: ' . json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
+			logger('deliver: local zot delivery succeeded to ' . $outq['outq_posturl']);
+			Libzot::process_response($outq['outq_posturl'],[ 'success' => true, 'body' => json_encode($result) ], $outq);
+		}
+		else {
+			logger('remote');
+			$channel = null;
+
+			if($outq['outq_channel']) {
+				$channel = channelx_by_n($outq['outq_channel']);
+			}
+
+			$host_crypto = null;
+
+			if($channel && $base) {
+				$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' order by hubloc_id desc limit 1",
+					dbesc($base)
+				);
+				if($h) {
+					$host_crypto = $h[0];
+				}
+			}
+
+			$msg = $outq['outq_notify'];
+
+			$result = Libzot::zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
+
+			if($result['success']) {
+				logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
+				Libzot::process_response($outq['outq_posturl'],$result, $outq);
+			}
+			else {
+				logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
+				logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
+				self::update($outq['outq_hash'],10);
+			}
+		}
+		return;
+	}
+}
+
diff --git a/Zotlabs/Lib/Webfinger.php b/Zotlabs/Lib/Webfinger.php
new file mode 100644
index 000000000..c2364ac4d
--- /dev/null
+++ b/Zotlabs/Lib/Webfinger.php
@@ -0,0 +1,109 @@
+ [ 'Accept: application/jrd+json, */*' ] ]);
+
+		if($s['success']) {
+			$j = json_decode($s['body'], true);
+			return($j);
+		}
+
+		return false;
+	}
+
+	static function parse_resource($resource) {
+
+		self::$resource = urlencode($resource);
+
+		if(strpos($resource,'http') === 0) {
+			$m = parse_url($resource);
+			if($m) {
+				if($m['scheme'] !== 'https') {
+					return false;
+				}
+				self::$server = $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
+			}
+			else {
+				return false;
+			}
+		}
+		elseif(strpos($resource,'tag:') === 0) {
+			$arr = explode(':',$resource); // split the tag
+			$h = explode(',',$arr[1]); // split the host,date
+			self::$server = $h[0];
+		}
+		else {
+			$x = explode('@',$resource);
+			$username = $x[0];
+			if(count($x) > 1) {
+				self::$server = $x[1];
+			}
+			else {
+				return false;
+			}
+			if(strpos($resource,'acct:') !== 0) {
+				self::$resource = urlencode('acct:' . $resource);
+			}
+		}
+
+	}
+
+	/**
+	 * @brief fetch a webfinger resource and return a zot6 discovery url if present
+	 *
+	 */ 
+
+	static function zot_url($resource) {
+
+		$arr = self::exec($resource);
+
+		if(is_array($arr) && array_key_exists('links',$arr)) {
+			foreach($arr['links'] as $link) {
+				if(array_key_exists('rel',$link) && $link['rel'] === PROTOCOL_ZOT6) {
+					if(array_key_exists('href',$link) && $link['href'] !== EMPTY_STR) {
+						return $link['href'];
+					}
+				}
+			}
+		}
+		return false;
+	}
+
+
+
+}
\ No newline at end of file
diff --git a/Zotlabs/Lib/Zotfinger.php b/Zotlabs/Lib/Zotfinger.php
new file mode 100644
index 000000000..537e440d4
--- /dev/null
+++ b/Zotlabs/Lib/Zotfinger.php
@@ -0,0 +1,50 @@
+ 'application/x-zot+json', 
+				'X-Zot-Token' => random_string(),
+			];
+			$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
+		}
+		else {
+			$h = [ 'Accept: application/x-zot+json' ]; 
+		}
+				
+		$result = [];
+
+
+		$redirects = 0;
+		$x = z_fetch_url($resource,false,$redirects, [ 'headers' => $h  ] );
+
+		if($x['success']) {
+			
+			$result['signature'] = HTTPSig::verify($x);
+    
+			$result['data'] = json_decode($x['body'],true);
+
+			if($result['data'] && is_array($result['data']) && array_key_exists('encrypted',$result['data']) && $result['data']['encrypted']) {
+				$result['data'] = json_decode(crypto_unencapsulate($result['data'],get_config('system','prvkey')),true);
+			}
+
+			return $result;
+		}
+
+		return false;
+	}
+
+
+
+}
\ No newline at end of file
diff --git a/Zotlabs/Module/Zot.php b/Zotlabs/Module/Zot.php
new file mode 100644
index 000000000..8c34dced1
--- /dev/null
+++ b/Zotlabs/Module/Zot.php
@@ -0,0 +1,25 @@
+run(),'application/x-zot+jzon');
+	}
+
+}
diff --git a/Zotlabs/Zot6/Finger.php b/Zotlabs/Zot6/Finger.php
new file mode 100644
index 000000000..f1fe41352
--- /dev/null
+++ b/Zotlabs/Zot6/Finger.php
@@ -0,0 +1,146 @@
+ true) or array('success' => false);
+	 */
+
+	static public function run($webbie, $channel = null, $autofallback = true) {
+
+		$ret = array('success' => false);
+
+		self::$token = random_string();
+
+		if (strpos($webbie, '@') === false) {
+			$address = $webbie;
+			$host = \App::get_hostname();
+		} else {
+			$address = substr($webbie,0,strpos($webbie,'@'));
+			$host = substr($webbie,strpos($webbie,'@')+1);
+			if(strpos($host,'/'))
+				$host = substr($host,0,strpos($host,'/'));
+		}
+
+		$xchan_addr = $address . '@' . $host;
+
+		if ((! $address) || (! $xchan_addr)) {
+			logger('zot_finger: no address :' . $webbie);
+
+			return $ret;
+		}
+
+		logger('using xchan_addr: ' . $xchan_addr, LOGGER_DATA, LOG_DEBUG);
+
+		// potential issue here; the xchan_addr points to the primary hub.
+		// The webbie we were called with may not, so it might not be found
+		// unless we query for hubloc_addr instead of xchan_addr
+
+		$r = q("select xchan.*, hubloc.* from xchan
+			left join hubloc on xchan_hash = hubloc_hash
+			where xchan_addr = '%s' and hubloc_primary = 1 limit 1",
+			dbesc($xchan_addr)
+		);
+
+		if($r) {
+			$url = $r[0]['hubloc_url'];
+
+			if($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') {
+				logger('zot_finger: alternate network: ' . $webbie);
+				logger('url: ' . $url . ', net: ' . var_export($r[0]['hubloc_network'],true), LOGGER_DATA, LOG_DEBUG);
+				return $ret;
+			}
+		} else {
+			$url = 'https://' . $host;
+		}
+
+		$rhs = '/.well-known/zot-info';
+		$https = ((strpos($url,'https://') === 0) ? true : false);
+
+		logger('zot_finger: ' . $address . ' at ' . $url, LOGGER_DEBUG);
+
+		if ($channel) {
+			$postvars = array(
+				'address'    => $address,
+				'target'     => $channel['channel_guid'],
+				'target_sig' => $channel['channel_guid_sig'],
+				'key'        => $channel['channel_pubkey'],
+				'token'      => self::$token
+			);
+
+			$headers = [];
+			$headers['X-Zot-Channel'] = $channel['channel_address'] . '@' . \App::get_hostname();
+			$headers['X-Zot-Nonce']   = random_string();
+			$xhead = \Zotlabs\Web\HTTPSig::create_sig('',$headers,$channel['channel_prvkey'],
+				'acct:' . $channel['channel_address'] . '@' . \App::get_hostname(),false);
+
+			$retries = 0;
+
+			$result = z_post_url($url . $rhs,$postvars,$retries, [ 'headers' => $xhead ]);
+
+			if ((! $result['success']) && ($autofallback)) {
+				if ($https) {
+					logger('zot_finger: https failed. falling back to http');
+					$result = z_post_url('http://' . $host . $rhs,$postvars, $retries, [ 'headers' => $xhead ]);
+				}
+			}
+		} 
+		else {
+			$rhs .= '?f=&address=' . urlencode($address) . '&token=' . self::$token;
+
+			$result = z_fetch_url($url . $rhs);
+			if((! $result['success']) && ($autofallback)) {
+				if($https) {
+					logger('zot_finger: https failed. falling back to http');
+					$result = z_fetch_url('http://' . $host . $rhs);
+				}
+			}
+		}
+
+		if(! $result['success']) {
+			logger('zot_finger: no results');
+
+			return $ret;
+		}
+
+		$x = json_decode($result['body'], true);
+
+		$verify = \Zotlabs\Web\HTTPSig::verify($result,(($x) ? $x['key'] : ''));
+
+		if($x && (! $verify['header_valid'])) {
+			$signed_token = ((is_array($x) && array_key_exists('signed_token', $x)) ? $x['signed_token'] : null);
+			if($signed_token) {
+				$valid = zot_verify('token.' . self::$token, base64url_decode($signed_token), $x['key']);
+				if(! $valid) {
+					logger('invalid signed token: ' . $url . $rhs, LOGGER_NORMAL, LOG_ERR);
+
+					return $ret;
+				}
+			}
+			else {
+				logger('No signed token from '  . $url . $rhs, LOGGER_NORMAL, LOG_WARNING);
+				return $ret;
+			}
+		}
+
+		return $x;
+	}
+
+}
diff --git a/Zotlabs/Zot6/IHandler.php b/Zotlabs/Zot6/IHandler.php
new file mode 100644
index 000000000..53b6caa89
--- /dev/null
+++ b/Zotlabs/Zot6/IHandler.php
@@ -0,0 +1,18 @@
+error       = false;
+		$this->validated   = false;
+		$this->messagetype = '';
+		$this->response    = [ 'success' => false ];
+		$this->handler     = $handler;
+		$this->data        = null;
+		$this->rawdata     = null;
+		$this->site_id     = null;
+		$this->prvkey      = Config::get('system','prvkey');
+
+		if($localdata) {
+			$this->rawdata = $localdata;
+		}
+		else {
+			$this->rawdata = file_get_contents('php://input');
+
+			// All access to the zot endpoint must use http signatures
+
+			if (! $this->Valid_Httpsig()) {
+				logger('signature failed');
+				$this->error = true;
+				$this->response['message'] = 'signature invalid';
+				return;
+			}
+		}
+
+		logger('received raw: ' . print_r($this->rawdata,true), LOGGER_DATA);
+
+
+		if ($this->rawdata) {
+			$this->data = json_decode($this->rawdata,true);
+		}
+		else {
+			$this->error = true;
+			$this->response['message'] = 'no data';
+		}
+
+		logger('received_json: ' . json_encode($this->data,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
+
+		logger('received: ' . print_r($this->data,true), LOGGER_DATA);
+
+		if ($this->data && is_array($this->data)) {
+			$this->encrypted = ((array_key_exists('encrypted',$this->data) && intval($this->data['encrypted'])) ? true : false);
+
+			if ($this->encrypted && $this->prvkey) {
+				$uncrypted = crypto_unencapsulate($this->data,$this->prvkey);
+				if ($uncrypted) {
+					$this->data = json_decode($uncrypted,true);
+				}
+				else {
+					$this->error = true;
+					$this->response['message'] = 'no data';
+				}
+			}
+		}
+	}
+
+
+	function run() {
+
+		if ($this->error) {
+			// make timing attacks on the decryption engine a bit more difficult
+			usleep(mt_rand(10000,100000));
+			return($this->response); 
+		}
+
+		if ($this->data) {
+			if (array_key_exists('type',$this->data)) {
+				$this->messagetype = $this->data['type'];
+			}
+
+			if (! $this->messagetype) {
+				$this->error = true;
+				$this->response['message'] = 'no datatype';
+				return $this->response;
+			}
+
+			$this->sender     = ((array_key_exists('sender',$this->data))     ? $this->data['sender'] : null);
+			$this->recipients = ((array_key_exists('recipients',$this->data)) ? $this->data['recipients'] : null);
+			$this->site_id    = ((array_key_exists('site_id',$this->data))    ? $this->data['site_id'] : null);
+		}
+
+		if ($this->sender) {
+			$result = $this->ValidateSender();
+			if (! $result) {
+				$this->error = true;
+				return $this->response;
+			}
+		}
+
+		return $this->Dispatch();
+	}
+
+	function ValidateSender() {
+
+		$hub = Libzot::valid_hub($this->sender,$this->site_id);
+
+		if (! $hub) {
+			$x = Libzot::register_hub($this->sigdata['signer']);
+			if($x['success']) {
+				$hub = Libzot::valid_hub($this->sender,$this->site_id);
+			}	
+			if(! $hub) {
+	           	$this->response['message'] = 'sender unknown';
+				return false;
+			}
+		}
+
+		if (! check_siteallowed($hub['hubloc_url'])) {
+			$this->response['message'] = 'forbidden';
+			return false;
+		}
+
+		if (! check_channelallowed($this->sender)) {
+			$this->response['message'] = 'forbidden';
+			return false;
+		}
+
+		Libzot::update_hub_connected($hub,$this->site_id);
+
+		$this->validated = true;
+		$this->hub = $hub;
+		return true;
+    }
+
+
+	function Valid_Httpsig() {
+
+		$result = false;
+
+		$this->sigdata = HTTPSig::verify($this->rawdata);
+
+		if ($this->sigdata && $this->sigdata['header_signed'] && $this->sigdata['header_valid']) {
+			$result = true;
+
+			// It is OK to not have signed content - not all messages provide content.
+			// But if it is signed, it has to be valid
+
+			if (($this->sigdata['content_signed']) && (! $this->sigdata['content_valid'])) {
+					$result = false;
+			}
+		}
+		return $result;
+	}	
+		
+	function Dispatch() {
+
+		switch ($this->messagetype) {
+
+			case 'request':
+				$this->response = $this->handler->Request($this->data,$this->hub);
+				break;
+
+			case 'purge':
+				$this->response = $this->handler->Purge($this->sender,$this->recipients,$this->hub);
+				break;
+
+			case 'refresh':
+				$this->response = $this->handler->Refresh($this->sender,$this->recipients,$this->hub);
+				break;
+
+			case 'rekey':
+				$this->response = $this->handler->Rekey($this->sender, $this->data,$this->hub);
+				break;
+
+			case 'activity':
+			case 'response': // upstream message
+			case 'sync':
+			default:
+				$this->response = $this->handler->Notify($this->data,$this->hub);
+				break;
+
+		}
+
+		logger('response_to_return: ' . print_r($this->response,true),LOGGER_DATA);
+
+		if ($this->encrypted) {
+			$this->EncryptResponse();
+		}
+
+		return($this->response); 
+	}
+
+	function EncryptResponse() {
+		$algorithm = Libzot::best_algorithm($this->hub['site_crypto']);
+		if ($algorithm) {
+			$this->response = crypto_encapsulate(json_encode($this->response),$this->hub['hubloc_sitekey'], $algorithm);
+		}
+	}
+
+}
+
+
+
diff --git a/Zotlabs/Zot6/Zot6Handler.php b/Zotlabs/Zot6/Zot6Handler.php
new file mode 100644
index 000000000..5597921cc
--- /dev/null
+++ b/Zotlabs/Zot6/Zot6Handler.php
@@ -0,0 +1,266 @@
+ false ];
+
+		logger('notify received from ' . $hub['hubloc_url']);
+
+		$x = Libzot::fetch($data);
+		$ret['delivery_report'] = $x;
+	
+
+		$ret['success'] = true;
+		return $ret;
+	}
+
+
+
+	/**
+	 * @brief Remote channel info (such as permissions or photo or something)
+	 * has been updated. Grab a fresh copy and sync it.
+	 *
+	 * The difference between refresh and force_refresh is that force_refresh
+	 * unconditionally creates a directory update record, even if no changes were
+	 * detected upon processing.
+	 *
+	 * @param array $sender
+	 * @param array $recipients
+	 *
+	 * @return json_return_and_die()
+	 */
+
+	static function reply_refresh($sender, $recipients,$hub) {
+		$ret = array('success' => false);
+
+		if($recipients) {
+
+			// 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_hash = xchan_hash
+					where channel_hash ='%s' limit 1",
+					dbesc($recip)
+				);
+
+				$x = Libzot::refresh( [ 'hubloc_id_url' => $hub['hubloc_id_url'] ], $r[0], (($msgtype === 'force_refresh') ? true : false));
+			}
+		}
+		else {
+			// system wide refresh
+
+			$x = Libzot::refresh( [ 'hubloc_id_url' => $hub['hubloc_id_url'] ], null, (($msgtype === 'force_refresh') ? true : false));
+		}
+
+		$ret['success'] = true;
+		return $ret;
+	}
+
+
+
+	/**
+	 * @brief Process a message request.
+	 *
+	 * If a site receives a comment to a post but finds they have no parent to attach it with, they
+	 * may send a 'request' packet containing the message_id of the missing parent. This is the handler
+	 * 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 
+	 * 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
+	 * @return array
+	 */
+	
+	static function reply_message_request($data,$hub) {
+		$ret = [ 'success' => false ];
+
+		$message_id = EMPTY_STR;
+
+		if(array_key_exists('data',$data))
+		$ptr = $data['data'];
+		if(is_array($ptr) && array_key_exists(0,$ptr)) {
+			$ptr = $ptr[0];
+		}
+		if(is_string($ptr)) {
+			$message_id = $ptr;
+		}
+		if(is_array($ptr) && array_key_exists('id',$ptr)) {
+			$message_id = $ptr['id'];
+		}
+
+		if (! $message_id) {
+			$ret['message'] = 'no message_id';
+			logger('no message_id');
+			return $ret;
+		}
+
+		$sender = $hub['hubloc_hash'];
+
+		/*
+		 * Find the local channel in charge of this post (the first and only recipient of the request packet)
+		 */
+
+		$arr = $data['recipients'][0];
+
+		$c = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_hash = '%s' limit 1",
+			dbesc($arr['portable_id'])
+		);
+		if (! $c) {
+			logger('recipient channel not found.');
+			$ret['message'] .= 'recipient not found.' . EOL;
+			return $ret;
+		}
+
+		/*
+		 * fetch the requested conversation
+		 */
+
+		$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) {
+
+		$ret = array('success' => false);
+
+		//	newsig is newkey signed with oldkey
+
+		// The original xchan will remain. In Zot/Receiver we will have imported the new xchan and hubloc to verify
+		// the packet authenticity. What we will do now is verify that the keychange operation was signed by the
+		// oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the
+		// old xchan_hash.
+
+		if((! $data['old_key']) && (! $data['new_key']) && (! $data['new_sig']))
+			return $ret;
+
+
+		$old = null;
+
+		if(Libzot::verify($data['old_guid'],$data['old_guid_sig'],$data['old_key'])) {
+			$oldhash = make_xchan_hash($data['old_guid'],$data['old_key']);
+			$old = q("select * from xchan where xchan_hash = '%s' limit 1",
+				dbesc($oldhash)
+			);
+		}
+		else 
+			return $ret;
+
+
+		if(! $old) {
+			return $ret;
+		}
+
+		$xchan = $old[0];
+
+		if(! Libzot::verify($data['new_key'],$data['new_sig'],$xchan['xchan_pubkey'])) {
+			return $ret;
+		}
+
+		$r = q("select * from xchan where xchan_hash = '%s' limit 1",
+			dbesc($sender)
+		);
+
+		$newxchan = $r[0];
+
+		// @todo
+		// if ! $update create a linked identity
+
+
+		xchan_change_key($xchan,$newxchan,$data);
+
+		$ret['success'] = true;
+		return $ret;
+	}
+
+
+	/**
+	 * @brief
+	 *
+	 * @param array $sender
+	 * @param array $recipients
+	 *
+	 * return json_return_and_die()
+	 */
+
+	static function reply_purge($sender, $recipients, $hub) {
+
+		$ret = array('success' => false);
+
+		if ($recipients) {
+			// basically this means "unfriend"
+			foreach ($recipients as $recip) {
+				$r = q("select channel.*,xchan.* from channel
+					left join xchan on channel_hash = xchan_hash
+					where channel_hash = '%s' and channel_guid_sig = '%s' limit 1",
+					dbesc($recip)
+				);
+				if ($r) {
+					$r = q("select abook_id from abook where uid = %d and abook_xchan = '%s' limit 1",
+						intval($r[0]['channel_id']),
+						dbesc($sender)
+					);
+					if ($r) {
+						contact_remove($r[0]['channel_id'],$r[0]['abook_id']);
+					}
+				}
+			}
+			$ret['success'] = true;
+		}
+		else {
+
+			// Unfriend everybody - basically this means the channel has committed suicide
+
+			remove_all_xchan_resources($sender);
+
+			$ret['success'] = true;
+		}
+
+		return $ret;
+	}
+
+
+
+
+
+
+}
-- 
cgit v1.2.3


From d3362dfa0c7e1cbd76342e83c480effc1b8765f8 Mon Sep 17 00:00:00 2001
From: Max Kostikov 
Date: Fri, 10 Aug 2018 16:56:22 +0200
Subject: Add translation for missed string

---
 Zotlabs/Module/Admin/Site.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'Zotlabs')

diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php
index 292de4c3a..5912a7c97 100644
--- a/Zotlabs/Module/Admin/Site.php
+++ b/Zotlabs/Module/Admin/Site.php
@@ -332,7 +332,7 @@ class Site {
 			'$register_policy'	=> array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices),
 			'$invite_only'		=> array('invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. Above register policy must be set to Yes.")),
 			'$minimum_age'		=> array('minimum_age', t("Minimum age"), (x(get_config('system','minimum_age'))?get_config('system','minimum_age'):13), t("Minimum age (in years) for who may register on this site.")),
-			'$access_policy'	=> array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), "This is displayed on the public server site list.", $access_choices),
+			'$access_policy'	=> array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), t("This is displayed on the public server site list."), $access_choices),
 			'$register_text'	=> array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")),
 			'$role'         => $role,
 			'$frontpage'	=> array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")),
-- 
cgit v1.2.3


From 0b31c677f253907ee9a36e12ae51763b2d69a574 Mon Sep 17 00:00:00 2001
From: "M.Dent" 
Date: Thu, 9 Aug 2018 22:35:12 -0400
Subject: Fixes to OAuth2 connect-with-openid.  Add zothash Claim.  Add
 zotwebbie Claim.

---
 Zotlabs/Identity/OAuth2Server.php  |  5 ++--
 Zotlabs/Identity/OAuth2Storage.php | 51 ++++++++++++++++++++++++++++++++++++--
 Zotlabs/Module/Authorize.php       | 12 ++++++---
 Zotlabs/Module/Token.php           |  8 +++---
 Zotlabs/Module/Userinfo.php        | 17 +++++++++++++
 5 files changed, 81 insertions(+), 12 deletions(-)
 create mode 100644 Zotlabs/Module/Userinfo.php

(limited to 'Zotlabs')

diff --git a/Zotlabs/Identity/OAuth2Server.php b/Zotlabs/Identity/OAuth2Server.php
index cbb4748fe..b747b95db 100644
--- a/Zotlabs/Identity/OAuth2Server.php
+++ b/Zotlabs/Identity/OAuth2Server.php
@@ -4,7 +4,7 @@ namespace Zotlabs\Identity;
 
 class OAuth2Server extends \OAuth2\Server {
 
-	public function __construct(OAuth2Storage $storage, $config = []) {
+	public function __construct(OAuth2Storage $storage, $config = null) {
 
 		if(! is_array($config)) {
 			$config = [
@@ -19,7 +19,8 @@ class OAuth2Server extends \OAuth2\Server {
 		$this->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage));
 
 		// Add the "Authorization Code" grant type (this is where the oauth magic happens)
-		$this->addGrantType(new \OAuth2\GrantType\AuthorizationCode($storage));
+                // Need to use OpenID\GrantType to return id_token (see:https://github.com/bshaffer/oauth2-server-php/issues/443)
+		$this->addGrantType(new \OAuth2\OpenID\GrantType\AuthorizationCode($storage));
 
 		$keyStorage = new \OAuth2\Storage\Memory( [
 			'keys' => [
diff --git a/Zotlabs/Identity/OAuth2Storage.php b/Zotlabs/Identity/OAuth2Storage.php
index bc6db565c..a50b21a70 100644
--- a/Zotlabs/Identity/OAuth2Storage.php
+++ b/Zotlabs/Identity/OAuth2Storage.php
@@ -50,20 +50,67 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
     public function getUser($username)
     {
 
-		$x = channelx_by_nick($username);
+		$x = channelx_by_n($username);
 		if(! $x) {
 			return false;
 		}
 
 		return( [
+                        'webbie'    => $x['channel_address'].'@'.\App::get_hostname(),
+                        'zothash'   => $x['channel_hash'],
 			'username'  => $x['channel_address'],
 			'user_id'   => $x['channel_id'],
+			'name'      => $x['channel_name'],
 			'firstName' => $x['channel_name'],
 			'lastName'  => '',
 			'password'  => 'NotARealPassword'
 		] );
     }
 
+    public function scopeExists($scope) {
+      // Report that the scope is valid even if it's not.
+      // We will only return a very small subset no matter what.
+      // @TODO: Truly validate the scope
+      //    see vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/ScopeInterface.php and
+      //        vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/Pdo.php
+      //    for more info.
+      return true;
+    }
+
+    public function getDefaultScope($client_id=null) {
+      // Do not REQUIRE a scope
+      //    see vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/ScopeInterface.php and
+      //    for more info.
+      return null;
+    }
+
+    public function getUserClaims ($user_id, $claims) {
+      // Populate the CLAIMS requested (if any).
+      // @TODO: create a more reasonable/comprehensive list.
+      // @TODO: present claims on the AUTHORIZATION screen
+
+        $userClaims = Array();
+        $claims = explode (' ', trim($claims));
+        $validclaims = Array ("name","preferred_username","zothash");
+        $claimsmap = Array (
+                            "zotwebbie" => 'webbie',
+                            "zothash" => 'zothash',
+                            "name" => 'name',
+                            "preferred_username" => "username"
+                           );
+        $userinfo = $this->getUser($user_id);
+        foreach ($validclaims as $validclaim) {
+            if (in_array($validclaim,$claims)) {
+              $claimkey = $claimsmap[$validclaim];
+              $userClaims[$validclaim] = $userinfo[$claimkey];
+            } else {
+              $userClaims[$validclaim] = $validclaim;
+            }
+        }
+        $userClaims["sub"]=$user_id;
+        return $userClaims; 
+    }
+
     /**
      * plaintext passwords are bad!  Override this for your application
      *
@@ -78,4 +125,4 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
         return true;
     }
 
-}
\ No newline at end of file
+}
diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php
index bfb76150f..e042848d8 100644
--- a/Zotlabs/Module/Authorize.php
+++ b/Zotlabs/Module/Authorize.php
@@ -60,12 +60,16 @@ class Authorize extends \Zotlabs\Web\Controller {
 		$request = \OAuth2\Request::createFromGlobals();
 		$response = new \OAuth2\Response();
 
+                // Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string. 
+                $channel = channelx_by_n(local_channel());
+		$user_id = $channel["channel_id"];
+
 		// If the client is not registered, add to the database
 		if (!$client = $storage->getClientDetails($client_id)) {
-			$client_secret = random_string(16);
+                        // Until "Dynamic Client Registration" is pursued - allow new clients to assign their own secret in the REQUEST
+			$client_secret = (isset($_REQUEST["client_secret"])) ? $_REQUEST["client_secret"] : random_string(16);
 			// Client apps are registered per channel
-			$user_id = local_channel();
-			$storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', null, $user_id);
+			$storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', urldecode($_REQUEST["scope"]), $user_id);
 			
 		}
 		if (!$client = $storage->getClientDetails($client_id)) {
@@ -83,7 +87,7 @@ class Authorize extends \Zotlabs\Web\Controller {
 
 		// print the authorization code if the user has authorized your client
 		$is_authorized = ($_POST['authorize'] === 'allow');
-		$s->handleAuthorizeRequest($request, $response, $is_authorized, local_channel());
+		$s->handleAuthorizeRequest($request, $response, $is_authorized, $user_id);
 		if ($is_authorized) {
 			$code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=') + 5, 40);
 			logger('Authorization Code: ' .  $code);
diff --git a/Zotlabs/Module/Token.php b/Zotlabs/Module/Token.php
index 32cf95c61..2bd33c761 100644
--- a/Zotlabs/Module/Token.php
+++ b/Zotlabs/Module/Token.php
@@ -27,11 +27,11 @@ class Token extends \Zotlabs\Web\Controller {
 				$_SERVER['PHP_AUTH_PW'] = $password;
 			}
 		}
-
-		$s = new \Zotlabs\Identity\OAuth2Server(new OAuth2Storage(\DBA::$dba->db));
+                $storage = new OAuth2Storage(\DBA::$dba->db);
+		$s = new \Zotlabs\Identity\OAuth2Server($storage);
 		$request = \OAuth2\Request::createFromGlobals();
-		$s->handleTokenRequest($request)->send();
-
+		$response = $s->handleTokenRequest($request);
+                $response->send();
 		killme();
 	}
 
diff --git a/Zotlabs/Module/Userinfo.php b/Zotlabs/Module/Userinfo.php
new file mode 100644
index 000000000..6c881f078
--- /dev/null
+++ b/Zotlabs/Module/Userinfo.php
@@ -0,0 +1,17 @@
+db));
+		$request = \OAuth2\Request::createFromGlobals();
+		$s->handleUserInfoRequest($request)->send();
+		killme();
+	}
+
+}
-- 
cgit v1.2.3


From e587fe5ce84ed5c248287eb55c6ae193ebd3222b Mon Sep 17 00:00:00 2001
From: "M.Dent" 
Date: Fri, 10 Aug 2018 12:44:57 -0400
Subject: Add user_id = local_channel() to the where clause of updates

---
 Zotlabs/Module/Settings/Oauth2.php | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'Zotlabs')

diff --git a/Zotlabs/Module/Settings/Oauth2.php b/Zotlabs/Module/Settings/Oauth2.php
index 985095115..52da20598 100644
--- a/Zotlabs/Module/Settings/Oauth2.php
+++ b/Zotlabs/Module/Settings/Oauth2.php
@@ -45,14 +45,15 @@ class Oauth2 {
 								grant_types = '%s',
 								scope = '%s', 
 								user_id = %d
-							WHERE client_id='%s'",
+							WHERE client_id='%s' and user_id = %s",
 							dbesc($name),
 							dbesc($secret),
 							dbesc($redirect),
 							dbesc($grant),
 							dbesc($scope),
 							intval(local_channel()),
-							dbesc($name));
+							dbesc($name),
+                                                        intval(local_channel()));
 				} else {
 					$r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id)
 						VALUES ('%s','%s','%s','%s','%s',%d)",
-- 
cgit v1.2.3


From af042ccf07b00af70b5e7844747dde9a263c697c Mon Sep 17 00:00:00 2001
From: "M.Dent" 
Date: Fri, 10 Aug 2018 13:51:45 -0400
Subject: OAuth2 UI and settings updates

---
 Zotlabs/Module/Settings/Oauth2.php | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

(limited to 'Zotlabs')

diff --git a/Zotlabs/Module/Settings/Oauth2.php b/Zotlabs/Module/Settings/Oauth2.php
index 52da20598..91abd1de3 100644
--- a/Zotlabs/Module/Settings/Oauth2.php
+++ b/Zotlabs/Module/Settings/Oauth2.php
@@ -10,10 +10,19 @@ class Oauth2 {
 	
 		if(x($_POST,'remove')){
 			check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2');
-			
+			$name   	= ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : '');
+		logger("REMOVE! ".$name." uid: ".local_channel());	
 			$key = $_POST['remove'];
-			q("DELETE FROM tokens WHERE id='%s' AND uid=%d",
-				dbesc($key),
+			q("DELETE FROM oauth_authorization_codes WHERE client_id='%s' AND user_id=%d",
+				dbesc($name),
+				intval(local_channel())
+			);
+			q("DELETE FROM oauth_access_tokens WHERE client_id='%s' AND user_id=%d",
+				dbesc($name),
+				intval(local_channel())
+			);
+			q("DELETE FROM oauth_refresh_tokens WHERE client_id='%s' AND user_id=%d",
+				dbesc($name),
 				intval(local_channel())
 			);
 			goaway(z_root()."/settings/oauth2/");
@@ -129,6 +138,18 @@ class Oauth2 {
 					dbesc(argv(3)),
 					intval(local_channel())
 			);
+			$r = q("DELETE FROM oauth_access_tokens WHERE client_id = '%s' AND user_id = %d",
+					dbesc(argv(3)),
+					intval(local_channel())
+			);
+			$r = q("DELETE FROM oauth_authorization_codes WHERE client_id = '%s' AND user_id = %d",
+					dbesc(argv(3)),
+					intval(local_channel())
+			);
+			$r = q("DELETE FROM oauth_refresh_tokens WHERE client_id = '%s' AND user_id = %d",
+					dbesc(argv(3)),
+					intval(local_channel())
+			);
 			goaway(z_root()."/settings/oauth2/");
 			return;			
 		}
@@ -136,7 +157,8 @@ class Oauth2 {
 
 		$r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my 
 				FROM oauth_clients
-				LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id
+				LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id AND
+                                                                 oauth_clients.user_id=oauth_access_tokens.user_id
 				WHERE oauth_clients.user_id IN (%d,0)",
 				intval(local_channel()),
 				intval(local_channel())
-- 
cgit v1.2.3


From 5afe779ffc69bc5889a83a6fcbc4bcefc7c40a5c Mon Sep 17 00:00:00 2001
From: zotlabs 
Date: Sat, 11 Aug 2018 16:16:54 -0700
Subject: prevent json-ld bombing, turn off browser autocomplete on channel
 sources creation

---
 Zotlabs/Module/Sources.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'Zotlabs')

diff --git a/Zotlabs/Module/Sources.php b/Zotlabs/Module/Sources.php
index 91e2efa60..2a2fa1835 100644
--- a/Zotlabs/Module/Sources.php
+++ b/Zotlabs/Module/Sources.php
@@ -111,7 +111,7 @@ class Sources extends \Zotlabs\Web\Controller {
 				'$title' => t('New Source'),
 				'$desc' => t('Import all or selected content from the following channel into this channel and distribute it according to your channel settings.'),
 				'$words' => array( 'words', t('Only import content with these words (one per line)'),'',t('Leave blank to import all public content')),
-				'$name' => array( 'name', t('Channel Name'), '', ''),
+				'$name' => array( 'name', t('Channel Name'), '', '', '', 'autocomplete="off"'),
 				'$tags' => array('tags', t('Add the following categories to posts imported from this source (comma separated)'),'',t('Optional')),
 				'$resend' => [ 'resend', t('Resend posts with this channel as author'), 0, t('Copyrights may apply'), [ t('No'), t('Yes') ]],  
 				'$submit' => t('Submit')
-- 
cgit v1.2.3


From 9402f537b62e80939d09ad602f96460e8ab66b1c Mon Sep 17 00:00:00 2001
From: "M.Dent" 
Date: Sun, 12 Aug 2018 19:02:11 -0400
Subject: Fix root not added to internationalized template search

---
 Zotlabs/Render/SmartyTemplate.php | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

(limited to 'Zotlabs')

diff --git a/Zotlabs/Render/SmartyTemplate.php b/Zotlabs/Render/SmartyTemplate.php
index ffe58e286..f14d63064 100755
--- a/Zotlabs/Render/SmartyTemplate.php
+++ b/Zotlabs/Render/SmartyTemplate.php
@@ -64,17 +64,20 @@ class SmartyTemplate implements TemplateEngine {
 	public function get_intltext_template($file, $root='') {
 
 		$lang = \App::$language;
-    
-		if(file_exists("view/$lang/$file"))
-        	$template_file = "view/$lang/$file";
-	    elseif(file_exists("view/en/$file"))
-        	$template_file = "view/en/$file";
-    	else
-        	$template_file = theme_include($file,$root);
+                if ($root != '' && substr($root,-1) != '/' ) {
+                               $root .= '/';
+                }
+                foreach (Array(
+                               $root."view/$lang/$file",
+                               $root."view/en/$file",
+                               ''
+                               ) as $template_file) {
+                        if (is_file($template_file)) { break; }
+                }
+                if ($template_file=='') {$template_file = theme_include($file,$root);}
 		if($template_file) {
 			$template = new SmartyInterface();
 			$template->filename = $template_file;
-
 			return $template;
 		}		
 		return "";
-- 
cgit v1.2.3


From 4fdf5d28caa5d4af2bc6dfc088fdd51111baf390 Mon Sep 17 00:00:00 2001
From: zotlabs 
Date: Mon, 13 Aug 2018 17:24:48 -0700
Subject: minor oauth2 updates - renamed zot webbie to 'webfinger' and zothash
 to 'portable_id', fixed/simplified cgi auth mode

---
 Zotlabs/Identity/OAuth2Storage.php | 35 +++++++++++++++++++++++------------
 Zotlabs/Module/Authorize.php       |  6 +++---
 2 files changed, 26 insertions(+), 15 deletions(-)

(limited to 'Zotlabs')

diff --git a/Zotlabs/Identity/OAuth2Storage.php b/Zotlabs/Identity/OAuth2Storage.php
index a50b21a70..bbf61cf2b 100644
--- a/Zotlabs/Identity/OAuth2Storage.php
+++ b/Zotlabs/Identity/OAuth2Storage.php
@@ -55,15 +55,22 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
 			return false;
 		}
 
+		$a = q("select * from account where account_id = %d",
+			intval($x['channel_account_id'])
+		);
+
+		$n = explode(' ', $x['channel_name']);
+
 		return( [
-                        'webbie'    => $x['channel_address'].'@'.\App::get_hostname(),
-                        'zothash'   => $x['channel_hash'],
-			'username'  => $x['channel_address'],
-			'user_id'   => $x['channel_id'],
-			'name'      => $x['channel_name'],
-			'firstName' => $x['channel_name'],
-			'lastName'  => '',
-			'password'  => 'NotARealPassword'
+			'webfinger'   => channel_reddress($x),
+			'portable_id' => $x['channel_hash'],
+			'email'       => $a['account_email'],
+			'username'    => $x['channel_address'],
+			'user_id'     => $x['channel_id'],
+			'name'        => $x['channel_name'],
+			'firstName'   => ((count($n) > 1) ? $n[1] : $n[0]),
+			'lastName'    => ((count($n) > 2) ? $n[count($n) - 1] : ''),
+			'picture'     => $x['xchan_photo_l']
 		] );
     }
 
@@ -91,12 +98,16 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
 
         $userClaims = Array();
         $claims = explode (' ', trim($claims));
-        $validclaims = Array ("name","preferred_username","zothash");
+        $validclaims = Array ("name","preferred_username","webfinger","portable_id","email","picture","firstName","lastName");
         $claimsmap = Array (
-                            "zotwebbie" => 'webbie',
-                            "zothash" => 'zothash',
+                            "webfinger" => 'webfinger',
+                            "portable_id" => 'portable_id',
                             "name" => 'name',
-                            "preferred_username" => "username"
+							"email" => 'email',
+                            "preferred_username" => 'username',
+							"picture" => 'picture',
+							"given_name" => 'firstName',
+							"family_name" => 'lastName'
                            );
         $userinfo = $this->getUser($user_id);
         foreach ($validclaims as $validclaim) {
diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php
index e042848d8..265dea661 100644
--- a/Zotlabs/Module/Authorize.php
+++ b/Zotlabs/Module/Authorize.php
@@ -14,9 +14,9 @@ class Authorize extends \Zotlabs\Web\Controller {
 			// OpenID Connect Dynamic Client Registration 1.0 Client Metadata
 			// http://openid.net/specs/openid-connect-registration-1_0.html
 			$app = array(
-				'name' => (x($_REQUEST, 'client_name') ? urldecode($_REQUEST['client_name']) : t('Unknown App')),
-				'icon' => (x($_REQUEST, 'logo_uri')    ? urldecode($_REQUEST['logo_uri']) : z_root() . '/images/icons/plugin.png'),
-				'url'  => (x($_REQUEST, 'client_uri')  ? urldecode($_REQUEST['client_uri']) : ''),
+				'name' => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : t('Unknown App')),
+				'icon' => (x($_REQUEST, 'logo_uri')  ? $_REQUEST['logo_uri'] : z_root() . '/images/icons/plugin.png'),
+				'url'  => (x($_REQUEST, 'client_uri')  ? $_REQUEST['client_uri'] : ''),
 			);
 			$o .= replace_macros(get_markup_template('oauth_authorize.tpl'), array(
 				'$title' => t('Authorize'),
-- 
cgit v1.2.3


From 62925c4c3f0fb184c194f0cb177c1525ccdb72cb Mon Sep 17 00:00:00 2001
From: zotlabs 
Date: Mon, 13 Aug 2018 20:24:04 -0700
Subject: oidc cleanup and discovery

---
 Zotlabs/Module/Authorize.php  | 56 ++++++++++++++++++++++++-------------------
 Zotlabs/Module/Oauthinfo.php  |  6 ++---
 Zotlabs/Module/Well_known.php |  1 +
 Zotlabs/Module/Wfinger.php    |  5 ++++
 4 files changed, 39 insertions(+), 29 deletions(-)

(limited to 'Zotlabs')

diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php
index 265dea661..c6709f602 100644
--- a/Zotlabs/Module/Authorize.php
+++ b/Zotlabs/Module/Authorize.php
@@ -7,27 +7,34 @@ use Zotlabs\Identity\OAuth2Storage;
 class Authorize extends \Zotlabs\Web\Controller {
 
 	function get() {
-		if (!local_channel()) {
+		if (! local_channel()) {
 			return login();
-		} else {
-			// TODO: Fully implement the dynamic client registration protocol:
-			// OpenID Connect Dynamic Client Registration 1.0 Client Metadata
-			// http://openid.net/specs/openid-connect-registration-1_0.html
-			$app = array(
-				'name' => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : t('Unknown App')),
-				'icon' => (x($_REQUEST, 'logo_uri')  ? $_REQUEST['logo_uri'] : z_root() . '/images/icons/plugin.png'),
+		} 
+		else {
+
+			$name = $_REQUEST['client_name'];
+			if(! $name) {
+				$name = (($_REQUEST['client_id']) ?: t('Unknown App'));
+			}
+
+			$app = [
+				'name' => $name,
+				'icon' => (x($_REQUEST, 'logo_uri')    ? $_REQUEST['logo_uri'] : z_root() . '/images/icons/plugin.png'),
 				'url'  => (x($_REQUEST, 'client_uri')  ? $_REQUEST['client_uri'] : ''),
-			);
-			$o .= replace_macros(get_markup_template('oauth_authorize.tpl'), array(
-				'$title' => t('Authorize'),
-				'$authorize' => sprintf( t('Do you authorize the app %s to access your channel data?'), '' . $app['name'] . ' '),
-				'$app' => $app,
-				'$yes' => t('Allow'),
-				'$no' => t('Deny'),
-				'$client_id' => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : ''),
+			];
+
+			$link = (($app['url']) ? '' . $app['name'] . ' ' : $app['name']);
+
+			$o .= replace_macros(get_markup_template('oauth_authorize.tpl'), [
+				'$title'        => t('Authorize'),
+				'$authorize'    => sprintf( t('Do you authorize the app %s to access your channel data?'), $link ),
+				'$app'          => $app,
+				'$yes'          => t('Allow'),
+				'$no'           => t('Deny'),
+				'$client_id'    => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : ''),
 				'$redirect_uri' => (x($_REQUEST, 'redirect_uri') ? $_REQUEST['redirect_uri'] : ''),
-				'$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : ''),
-			));
+				'$state'        => (x($_REQUEST, 'state') ? $_REQUEST['state'] : ''),
+			]);
 			return $o;
 		}
 	}
@@ -60,17 +67,16 @@ class Authorize extends \Zotlabs\Web\Controller {
 		$request = \OAuth2\Request::createFromGlobals();
 		$response = new \OAuth2\Response();
 
-                // Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string. 
-                $channel = channelx_by_n(local_channel());
-		$user_id = $channel["channel_id"];
+		// Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string. 
+		$channel = channelx_by_n(local_channel());
+		$user_id = $channel['channel_id'];
 
 		// If the client is not registered, add to the database
 		if (!$client = $storage->getClientDetails($client_id)) {
-                        // Until "Dynamic Client Registration" is pursued - allow new clients to assign their own secret in the REQUEST
-			$client_secret = (isset($_REQUEST["client_secret"])) ? $_REQUEST["client_secret"] : random_string(16);
+			// Until "Dynamic Client Registration" is pursued - allow new clients to assign their own secret in the REQUEST
+			$client_secret = (isset($_REQUEST['client_secret'])) ? $_REQUEST['client_secret'] : random_string(16);
 			// Client apps are registered per channel
-			$storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', urldecode($_REQUEST["scope"]), $user_id);
-			
+			$storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', $_REQUEST['scope'], $user_id);
 		}
 		if (!$client = $storage->getClientDetails($client_id)) {
 			// There was an error registering the client.
diff --git a/Zotlabs/Module/Oauthinfo.php b/Zotlabs/Module/Oauthinfo.php
index 2d10913c4..f380cec97 100644
--- a/Zotlabs/Module/Oauthinfo.php
+++ b/Zotlabs/Module/Oauthinfo.php
@@ -5,19 +5,17 @@ namespace Zotlabs\Module;
 
 class Oauthinfo extends \Zotlabs\Web\Controller {
 
-
 	function init() {
 
 		$ret = [
 			'issuer'                   => z_root(),
 			'authorization_endpoint'   => z_root() . '/authorize',
 			'token_endpoint'           => z_root() . '/token',
+			'userinfo_endpoint'        => z_root() . '/userinfo',
+			'scopes_supported'         => [ 'openid', 'profile', 'email' ],
 			'response_types_supported' => [ 'code', 'token', 'id_token', 'code id_token', 'token id_token' ] 
 		];
 
-
 		json_return_and_die($ret);
 	}
-
-
 }
\ No newline at end of file
diff --git a/Zotlabs/Module/Well_known.php b/Zotlabs/Module/Well_known.php
index 442994b54..09e743788 100644
--- a/Zotlabs/Module/Well_known.php
+++ b/Zotlabs/Module/Well_known.php
@@ -52,6 +52,7 @@ class Well_known extends \Zotlabs\Web\Controller {
 					break;
 
 				case 'oauth-authorization-server':
+				case 'openid-configuration':
 					\App::$argc -= 1;
 					array_shift(\App::$argv);
 					\App::$argv[0] = 'oauthinfo';
diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php
index 88cb3e879..1866bce40 100644
--- a/Zotlabs/Module/Wfinger.php
+++ b/Zotlabs/Module/Wfinger.php
@@ -172,6 +172,11 @@ class Wfinger extends \Zotlabs\Web\Controller {
 						'href' => z_root() . '/hcard/' . $r[0]['channel_address']	
 					],
 
+					[
+						'rel'  => 'http://openid.net/specs/connect/1.0/issuer',
+						'href' => z_root()
+					],
+
 
 					[
 						'rel'  => 'http://webfinger.net/rel/profile-page',
-- 
cgit v1.2.3


From f15c1c4e54a49d1e76747ca5e3034ca2cef909aa Mon Sep 17 00:00:00 2001
From: zotlabs 
Date: Mon, 13 Aug 2018 21:18:20 -0700
Subject: hubloc DB changes needed for z6

---
 Zotlabs/Update/_1218.php | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 Zotlabs/Update/_1218.php

(limited to 'Zotlabs')

diff --git a/Zotlabs/Update/_1218.php b/Zotlabs/Update/_1218.php
new file mode 100644
index 000000000..67d8b49a5
--- /dev/null
+++ b/Zotlabs/Update/_1218.php
@@ -0,0 +1,31 @@
+
Date: Mon, 13 Aug 2018 23:11:10 -0700
Subject: issue with mdpost addon and archive.org links which contain a full
 url as a path/query component

---
 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 ef1eb3700..640b4fa5c 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -533,7 +533,7 @@ class Item extends \Zotlabs\Web\Controller {
 	
 			// Look for tags and linkify them
 			$results = linkify_tags($a, $body, ($uid) ? $uid : $profile_uid);
-logger('linkify: ' . print_r($results,true));
+
 			if($results) {
 	
 				// Set permissions based on tag replacements
-- 
cgit v1.2.3


From f230c07ba5ed71c0491c6fd109c0789d2cc341c1 Mon Sep 17 00:00:00 2001
From: zotlabs 
Date: Wed, 15 Aug 2018 17:00:37 -0700
Subject: possible fixes for can_comment_on_post(), provide wiki_list on wiki
 sidebar

---
 Zotlabs/Lib/ThreadStream.php | 1 -
 Zotlabs/Widget/Wiki_list.php | 6 +++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

(limited to 'Zotlabs')

diff --git a/Zotlabs/Lib/ThreadStream.php b/Zotlabs/Lib/ThreadStream.php
index d0c964149..020e8729b 100644
--- a/Zotlabs/Lib/ThreadStream.php
+++ b/Zotlabs/Lib/ThreadStream.php
@@ -196,7 +196,6 @@ class ThreadStream {
 			$item->set_commentable(false);
 		} 
 
-		require_once('include/channel.php');
 
 		$item->set_conversation($this);
 		$this->threads[] = $item;
diff --git a/Zotlabs/Widget/Wiki_list.php b/Zotlabs/Widget/Wiki_list.php
index 62f32dbf0..c8d83cbe8 100644
--- a/Zotlabs/Widget/Wiki_list.php
+++ b/Zotlabs/Widget/Wiki_list.php
@@ -6,13 +6,17 @@ class Wiki_list {
 
 	function widget($arr) {
 
+		if(argc() < 3) {
+			return;
+		}
+
 		$channel = channelx_by_n(\App::$profile_uid);
 
 		$wikis = \Zotlabs\Lib\NativeWiki::listwikis($channel,get_observer_hash());
 
 		if($wikis) {
 			return replace_macros(get_markup_template('wikilist_widget.tpl'), array(
-				'$header' => t('Wiki List'),
+				'$header' => t('Wikis'),
 				'$channel' => $channel['channel_address'],
 				'$wikis' => $wikis['wikis']
 			));
-- 
cgit v1.2.3


From 32acb0ff01b8fde3801fafbd7953aa36b5933f96 Mon Sep 17 00:00:00 2001
From: zotlabs 
Date: Wed, 15 Aug 2018 21:33:11 -0700
Subject: missing files

---
 Zotlabs/Module/Zot_probe.php |  47 ++++
 Zotlabs/Zot6/HTTPSig.php     | 507 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 554 insertions(+)
 create mode 100644 Zotlabs/Module/Zot_probe.php
 create mode 100644 Zotlabs/Zot6/HTTPSig.php

(limited to 'Zotlabs')

diff --git a/Zotlabs/Module/Zot_probe.php b/Zotlabs/Module/Zot_probe.php
new file mode 100644
index 000000000..d0c7e688f
--- /dev/null
+++ b/Zotlabs/Module/Zot_probe.php
@@ -0,0 +1,47 @@
+Zot6 Probe Diagnostic';
+	
+		$o .= '
'; + $o .= 'Lookup URI:
'; + $o .= '
'; + + $o .= '

'; + + if(x($_GET,'addr')) { + $addr = $_GET['addr']; + + + $x = Zotfinger::exec($addr); + + $o .= '
' . htmlspecialchars(print_array($x)) . '
'; + + $headers = 'Accept: application/x-zot+json, application/jrd+json, application/json'; + + $redirects = 0; + $x = z_fetch_url($addr,true,$redirects, [ 'headers' => [ $headers ]]); + + if($x['success']) { + + $o .= '
' . htmlspecialchars($x['header']) . '
' . EOL; + + $o .= 'verify returns: ' . str_replace("\n",EOL,print_r(HTTPSig::verify($x),true)) . EOL; + + $o .= '
' . htmlspecialchars(json_encode(json_decode($x['body']),JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)) . '
' . EOL; + + } + + } + return $o; + } + +} diff --git a/Zotlabs/Zot6/HTTPSig.php b/Zotlabs/Zot6/HTTPSig.php new file mode 100644 index 000000000..a0f0d3500 --- /dev/null +++ b/Zotlabs/Zot6/HTTPSig.php @@ -0,0 +1,507 @@ +fetcharr(); + $body = $data['body']; + } + + else { + $headers = []; + $headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; + $headers['content-type'] = $_SERVER['CONTENT_TYPE']; + + foreach($_SERVER as $k => $v) { + if(strpos($k,'HTTP_') === 0) { + $field = str_replace('_','-',strtolower(substr($k,5))); + $headers[$field] = $v; + } + } + } + + //logger('SERVER: ' . print_r($_SERVER,true), LOGGER_ALL); + + //logger('headers: ' . print_r($headers,true), LOGGER_ALL); + + return $headers; + } + + + // See draft-cavage-http-signatures-10 + + static function verify($data,$key = '') { + + $body = $data; + $headers = null; + + $result = [ + 'signer' => '', + 'portable_id' => '', + 'header_signed' => false, + 'header_valid' => false, + 'content_signed' => false, + 'content_valid' => false + ]; + + + $headers = self::find_headers($data,$body); + + if(! $headers) + return $result; + + $sig_block = null; + + if(array_key_exists('signature',$headers)) { + $sig_block = self::parse_sigheader($headers['signature']); + } + elseif(array_key_exists('authorization',$headers)) { + $sig_block = self::parse_sigheader($headers['authorization']); + } + + if(! $sig_block) { + logger('no signature provided.', LOGGER_DEBUG); + return $result; + } + + // Warning: This log statement includes binary data + // logger('sig_block: ' . print_r($sig_block,true), LOGGER_DATA); + + $result['header_signed'] = true; + + $signed_headers = $sig_block['headers']; + if(! $signed_headers) + $signed_headers = [ 'date' ]; + + $signed_data = ''; + foreach($signed_headers as $h) { + if(array_key_exists($h,$headers)) { + $signed_data .= $h . ': ' . $headers[$h] . "\n"; + } + } + $signed_data = rtrim($signed_data,"\n"); + + $algorithm = null; + if($sig_block['algorithm'] === 'rsa-sha256') { + $algorithm = 'sha256'; + } + if($sig_block['algorithm'] === 'rsa-sha512') { + $algorithm = 'sha512'; + } + + if(! array_key_exists('keyId',$sig_block)) + return $result; + + $result['signer'] = $sig_block['keyId']; + + $key = self::get_key($key,$result['signer']); + + if(! ($key && $key['public_key'])) { + return $result; + } + + $x = rsa_verify($signed_data,$sig_block['signature'],$key['public_key'],$algorithm); + + logger('verified: ' . $x, LOGGER_DEBUG); + + if(! $x) + return $result; + + $result['portable_id'] = $key['portable_id']; + $result['header_valid'] = true; + + if(in_array('digest',$signed_headers)) { + $result['content_signed'] = true; + $digest = explode('=', $headers['digest'], 2); + if($digest[0] === 'SHA-256') + $hashalg = 'sha256'; + if($digest[0] === 'SHA-512') + $hashalg = 'sha512'; + + if(base64_encode(hash($hashalg,$body,true)) === $digest[1]) { + $result['content_valid'] = true; + } + + logger('Content_Valid: ' . (($result['content_valid']) ? 'true' : 'false')); + } + + return $result; + } + + static function get_key($key,$id) { + + if($key) { + if(function_exists($key)) { + return $key($id); + } + return [ 'public_key' => $key ]; + } + + $key = self::get_webfinger_key($id); + + if(! $key) { + $key = self::get_activitystreams_key($id); + } + + return $key; + + } + + + function convertKey($key) { + + if(strstr($key,'RSA ')) { + return rsatopem($key); + } + elseif(substr($key,0,5) === 'data:') { + return convert_salmon_key($key); + } + else { + return $key; + } + + } + + + /** + * @brief + * + * @param string $id + * @return boolean|string + * false if no pub key found, otherwise return the pub key + */ + + function get_activitystreams_key($id) { + + $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' limit 1", + dbesc(str_replace('acct:','',$id)), + dbesc($id) + ); + + if($x && $x[0]['xchan_pubkey']) { + return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ]; + } + + $r = ActivityStreams::fetch_property($id); + + if($r) { + if(array_key_exists('publicKey',$j) && array_key_exists('publicKeyPem',$j['publicKey']) && array_key_exists('id',$j['publicKey'])) { + if($j['publicKey']['id'] === $id || $j['id'] === $id) { + return [ 'public_key' => self::convertKey($j['publicKey']['publicKeyPem']), 'portable_id' => '', 'hubloc' => [] ]; + } + } + } + + return false; + } + + + function get_webfinger_key($id) { + + $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' limit 1", + dbesc(str_replace('acct:','',$id)), + dbesc($id) + ); + + if($x && $x[0]['xchan_pubkey']) { + return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ]; + } + + $wf = Webfinger::exec($id); + $key = [ 'portable_id' => '', 'public_key' => '', 'hubloc' => [] ]; + + if($wf) { + if(array_key_exists('properties',$wf) && array_key_exists('https://w3id.org/security/v1#publicKeyPem',$wf['properties'])) { + $key['public_key'] = self::convertKey($wf['properties']['https://w3id.org/security/v1#publicKeyPem']); + } + if(array_key_exists('links', $wf) && is_array($wf['links'])) { + foreach($wf['links'] as $l) { + if(! (is_array($l) && array_key_exists('rel',$l))) { + continue; + } + if($l['rel'] === 'magic-public-key' && array_key_exists('href',$l) && $key['public_key'] === EMPTY_STR) { + $key['public_key'] = self::convertKey($l['href']); + } + } + } + } + + return (($key['public_key']) ? $key : false); + } + + + function get_zotfinger_key($id) { + + $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' limit 1", + dbesc(str_replace('acct:','',$id)), + dbesc($id) + ); + if($x && $x[0]['xchan_pubkey']) { + return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ]; + } + + $wf = Webfinger::exec($id); + $key = [ 'portable_id' => '', 'public_key' => '', 'hubloc' => [] ]; + + if($wf) { + if(array_key_exists('properties',$wf) && array_key_exists('https://w3id.org/security/v1#publicKeyPem',$wf['properties'])) { + $key['public_key'] = self::convertKey($wf['properties']['https://w3id.org/security/v1#publicKeyPem']); + } + if(array_key_exists('links', $wf) && is_array($wf['links'])) { + foreach($wf['links'] as $l) { + if(! (is_array($l) && array_key_exists('rel',$l))) { + continue; + } + if($l['rel'] === 'http://purl.org/zot/protocol/6.0' && array_key_exists('href',$l) && $l['href'] !== EMPTY_STR) { + $z = \Zotlabs\Lib\Zotfinger::exec($l['href']); + if($z) { + $i = Zotlabs\Lib\Libzot::import_xchan($z['data']); + if($i['success']) { + $key['portable_id'] = $i['hash']; + + $x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1", + dbesc($l['href']) + ); + if($x) { + $key['hubloc'] = $x[0]; + } + } + } + } + if($l['rel'] === 'magic-public-key' && array_key_exists('href',$l) && $key['public_key'] === EMPTY_STR) { + $key['public_key'] = self::convertKey($l['href']); + } + } + } + } + + return (($key['public_key']) ? $key : false); + } + + + /** + * @brief + * + * @param array $head + * @param string $prvkey + * @param string $keyid (optional, default '') + * @param boolean $auth (optional, default false) + * @param string $alg (optional, default 'sha256') + * @param array $encryption [ 'key', 'algorithm' ] or false + * @return array + */ + static function create_sig($head, $prvkey, $keyid = EMPTY_STR, $auth = false, $alg = 'sha256', $encryption = false ) { + + $return_headers = []; + + if($alg === 'sha256') { + $algorithm = 'rsa-sha256'; + } + if($alg === 'sha512') { + $algorithm = 'rsa-sha512'; + } + + $x = self::sign($head,$prvkey,$alg); + + $headerval = 'keyId="' . $keyid . '",algorithm="' . $algorithm . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"'; + + if($encryption) { + $x = crypto_encapsulate($headerval,$encryption['key'],$encryption['algorithm']); + if(is_array($x)) { + $headerval = 'iv="' . $x['iv'] . '",key="' . $x['key'] . '",alg="' . $x['alg'] . '",data="' . $x['data'] . '"'; + } + } + + if($auth) { + $sighead = 'Authorization: Signature ' . $headerval; + } + else { + $sighead = 'Signature: ' . $headerval; + } + + if($head) { + foreach($head as $k => $v) { + // strip the request-target virtual header from the output headers + if($k === '(request-target)') { + continue; + } + $return_headers[] = $k . ': ' . $v; + } + } + $return_headers[] = $sighead; + + return $return_headers; + } + + /** + * @brief set headers + * + * @param array $headers + * @return void + */ + + + static function set_headers($headers) { + if($headers && is_array($headers)) { + foreach($headers as $h) { + header($h); + } + } + } + + + /** + * @brief + * + * @param array $head + * @param string $prvkey + * @param string $alg (optional) default 'sha256' + * @return array + */ + + static function sign($head, $prvkey, $alg = 'sha256') { + + $ret = []; + + $headers = ''; + $fields = ''; + + if($head) { + foreach($head as $k => $v) { + $headers .= strtolower($k) . ': ' . trim($v) . "\n"; + if($fields) + $fields .= ' '; + + $fields .= strtolower($k); + } + // strip the trailing linefeed + $headers = rtrim($headers,"\n"); + } + + $sig = base64_encode(rsa_sign($headers,$prvkey,$alg)); + + $ret['headers'] = $fields; + $ret['signature'] = $sig; + + return $ret; + } + + /** + * @brief + * + * @param string $header + * @return array associate array with + * - \e string \b keyID + * - \e string \b algorithm + * - \e array \b headers + * - \e string \b signature + */ + + static function parse_sigheader($header) { + + $ret = []; + $matches = []; + + // if the header is encrypted, decrypt with (default) site private key and continue + + if(preg_match('/iv="(.*?)"/ism',$header,$matches)) + $header = self::decrypt_sigheader($header); + + if(preg_match('/keyId="(.*?)"/ism',$header,$matches)) + $ret['keyId'] = $matches[1]; + if(preg_match('/algorithm="(.*?)"/ism',$header,$matches)) + $ret['algorithm'] = $matches[1]; + if(preg_match('/headers="(.*?)"/ism',$header,$matches)) + $ret['headers'] = explode(' ', $matches[1]); + if(preg_match('/signature="(.*?)"/ism',$header,$matches)) + $ret['signature'] = base64_decode(preg_replace('/\s+/','',$matches[1])); + + if(($ret['signature']) && ($ret['algorithm']) && (! $ret['headers'])) + $ret['headers'] = [ 'date' ]; + + return $ret; + } + + + /** + * @brief + * + * @param string $header + * @param string $prvkey (optional), if not set use site private key + * @return array|string associative array, empty string if failue + * - \e string \b iv + * - \e string \b key + * - \e string \b alg + * - \e string \b data + */ + + static function decrypt_sigheader($header, $prvkey = null) { + + $iv = $key = $alg = $data = null; + + if(! $prvkey) { + $prvkey = get_config('system', 'prvkey'); + } + + $matches = []; + + if(preg_match('/iv="(.*?)"/ism',$header,$matches)) + $iv = $matches[1]; + if(preg_match('/key="(.*?)"/ism',$header,$matches)) + $key = $matches[1]; + if(preg_match('/alg="(.*?)"/ism',$header,$matches)) + $alg = $matches[1]; + if(preg_match('/data="(.*?)"/ism',$header,$matches)) + $data = $matches[1]; + + if($iv && $key && $alg && $data) { + return crypto_unencapsulate([ 'encrypted' => true, 'iv' => $iv, 'key' => $key, 'alg' => $alg, 'data' => $data ] , $prvkey); + } + + return ''; + } + +} -- cgit v1.2.3 From d95735deaf321eb560b3fdc0b88d25bca4be3b48 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 20 Aug 2018 17:22:49 -0700 Subject: channel page performance improvement: don't use "checkjs" with an associated page reload. Wrap a static copy of the content in noscript tags instead. --- Zotlabs/Module/Channel.php | 86 ++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 42 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index b5e6b3aee..f1ae2f507 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module; +use \App; + require_once('include/contact_widgets.php'); require_once('include/items.php'); require_once("include/bbcode.php"); @@ -26,7 +28,7 @@ class Channel extends \Zotlabs\Web\Controller { $which = argv(1); if(! $which) { if(local_channel()) { - $channel = \App::get_channel(); + $channel = App::get_channel(); if($channel && $channel['channel_address']) $which = $channel['channel_address']; } @@ -37,7 +39,7 @@ class Channel extends \Zotlabs\Web\Controller { } $profile = 0; - $channel = \App::get_channel(); + $channel = App::get_channel(); if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) { $which = $channel['channel_address']; @@ -70,8 +72,6 @@ class Channel extends \Zotlabs\Web\Controller { if($load) $_SESSION['loadtime'] = datetime_convert(); - $checkjs = new \Zotlabs\Web\CheckJS(1); - $category = $datequery = $datequery2 = ''; $mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : ''); @@ -95,22 +95,22 @@ class Channel extends \Zotlabs\Web\Controller { if($update) { // Ensure we've got a profile owner if updating. - \App::$profile['profile_uid'] = \App::$profile_uid = $update; + App::$profile['profile_uid'] = App::$profile_uid = $update; } - $is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false); + $is_owner = (((local_channel()) && (App::$profile['profile_uid'] == local_channel())) ? true : false); - $channel = \App::get_channel(); - $observer = \App::get_observer(); + $channel = App::get_channel(); + $observer = App::get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); - $perms = get_all_perms(\App::$profile['profile_uid'],$ob_hash); + $perms = get_all_perms(App::$profile['profile_uid'],$ob_hash); if(! $perms['view_stream']) { // We may want to make the target of this redirect configurable if($perms['view_profile']) { notice( t('Insufficient permissions. Request redirected to profile page.') . EOL); - goaway (z_root() . "/profile/" . \App::$profile['channel_address']); + goaway (z_root() . "/profile/" . App::$profile['channel_address']); } notice( t('Permission denied.') . EOL); return; @@ -121,7 +121,7 @@ class Channel extends \Zotlabs\Web\Controller { nav_set_selected('Channel Home'); - $static = channel_manual_conv_update(\App::$profile['profile_uid']); + $static = channel_manual_conv_update(App::$profile['profile_uid']); // search terms header if($search) { @@ -147,16 +147,16 @@ class Channel extends \Zotlabs\Web\Controller { $x = array( 'is_owner' => $is_owner, - 'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(\App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false), - 'default_location' => (($is_owner) ? \App::$profile['channel_location'] : ''), - 'nickname' => \App::$profile['channel_address'], - 'lockstate' => (((strlen(\App::$profile['channel_allow_cid'])) || (strlen(\App::$profile['channel_allow_gid'])) || (strlen(\App::$profile['channel_deny_cid'])) || (strlen(\App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'), + 'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false), + 'default_location' => (($is_owner) ? App::$profile['channel_location'] : ''), + 'nickname' => App::$profile['channel_address'], + 'lockstate' => (((strlen(App::$profile['channel_allow_cid'])) || (strlen(App::$profile['channel_allow_gid'])) || (strlen(App::$profile['channel_deny_cid'])) || (strlen(App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'), 'acl' => (($is_owner) ? populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''), 'permissions' => $channel_acl, 'showacl' => (($is_owner) ? 'yes' : ''), 'bang' => '', 'visitor' => (($is_owner || $observer) ? true : false), - 'profile_uid' => \App::$profile['profile_uid'], + 'profile_uid' => App::$profile['profile_uid'], 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true, @@ -176,14 +176,14 @@ class Channel extends \Zotlabs\Web\Controller { $item_normal = item_normal(); $item_normal_update = item_normal_update(); - $sql_extra = item_permissions_sql(\App::$profile['profile_uid']); + $sql_extra = item_permissions_sql(App::$profile['profile_uid']); - if(get_pconfig(\App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid)) + if(get_pconfig(App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid)) $page_mode = 'list'; else $page_mode = 'client'; - $abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " "; + $abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " "; $simple_update = (($update) ? " AND item_unseen = 1 " : ''); @@ -203,7 +203,7 @@ class Channel extends \Zotlabs\Web\Controller { head_add_link([ 'rel' => 'alternate', 'type' => 'application/json+oembed', - 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string), 'title' => 'oembed' ]); @@ -221,7 +221,7 @@ class Channel extends \Zotlabs\Web\Controller { $r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update AND item_wall = 1 $simple_update $sql_extra limit 1", dbesc($mid . '%'), - intval(\App::$profile['profile_uid']) + intval(App::$profile['profile_uid']) ); $_SESSION['loadtime'] = datetime_convert(); } @@ -233,7 +233,7 @@ class Channel extends \Zotlabs\Web\Controller { AND (abook.abook_blocked = 0 or abook.abook_flags is null) $sql_extra ORDER BY created DESC", - intval(\App::$profile['profile_uid']) + intval(App::$profile['profile_uid']) ); $_SESSION['loadtime'] = datetime_convert(); } @@ -242,10 +242,10 @@ class Channel extends \Zotlabs\Web\Controller { else { if(x($category)) { - $sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY)); + $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY)); } if(x($hashtags)) { - $sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG)); + $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG)); } if($datequery) { @@ -267,15 +267,15 @@ class Channel extends \Zotlabs\Web\Controller { $itemspage = get_pconfig(local_channel(),'system','itemspage'); - \App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); - if($load || ($checkjs->disabled())) { + if((! $update) || ($load)) { if($mid) { $r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal AND item_wall = 1 $sql_extra limit 1", dbesc($mid . '%'), - intval(\App::$profile['profile_uid']) + intval(App::$profile['profile_uid']) ); if (! $r) { notice( t('Permission denied.') . EOL); @@ -289,7 +289,7 @@ class Channel extends \Zotlabs\Web\Controller { AND item.item_wall = 1 AND item.item_thread_top = 1 $sql_extra $sql_extra2 ORDER BY $ordering DESC $pager_sql ", - intval(\App::$profile['profile_uid']) + intval(App::$profile['profile_uid']) ); } } @@ -306,7 +306,7 @@ class Channel extends \Zotlabs\Web\Controller { WHERE item.uid = %d $item_normal AND item.parent IN ( %s ) $sql_extra ", - intval(\App::$profile['profile_uid']), + intval(App::$profile['profile_uid']), dbesc($parents_str) ); @@ -329,19 +329,19 @@ class Channel extends \Zotlabs\Web\Controller { // This is ugly, but we can't pass the profile_uid through the session to the ajax updater, // because browser prefetching might change it on us. We have to deliver it with the page. - $maxheight = get_pconfig(\App::$profile['profile_uid'],'system','channel_divmore_height'); + $maxheight = get_pconfig(App::$profile['profile_uid'],'system','channel_divmore_height'); if(! $maxheight) $maxheight = 400; $o .= '
' . "\r\n"; - $o .= "\r\n"; - \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( + App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( '$baseurl' => z_root(), '$pgtype' => 'channel', - '$uid' => ((\App::$profile['profile_uid']) ? \App::$profile['profile_uid'] : '0'), + '$uid' => ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : '0'), '$gid' => '0', '$cid' => '0', '$cmin' => '(-1)', @@ -354,7 +354,7 @@ class Channel extends \Zotlabs\Web\Controller { '$wall' => '1', '$fh' => '0', '$static' => $static, - '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), + '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), '$search' => $search, '$xchan' => '', '$order' => $order, @@ -405,17 +405,19 @@ class Channel extends \Zotlabs\Web\Controller { $mode = (($search) ? 'search' : 'channel'); - if($checkjs->disabled()) { - $o .= conversation($items,$mode,$update,'traditional'); + if($update) { + $o .= conversation($items,$mode,$update,$page_mode); } else { + $o .= ''; $o .= conversation($items,$mode,$update,$page_mode); - } - if((! $update) || ($checkjs->disabled())) { - $o .= alt_pager(count($items)); if ($mid && $items[0]['title']) - \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title']; + App::$page['title'] = $items[0]['title'] . " - " . App::$page['title']; + } if($mid) -- cgit v1.2.3 From a9bbfe9c4f0b783433ceb6c586022093e74aa718 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 20 Aug 2018 17:38:38 -0700 Subject: Only show cover photos once per login session. After that they can get annoying. If there is pushback on this, then it should perhaps be optional. --- Zotlabs/Widget/Cover_photo.php | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Cover_photo.php b/Zotlabs/Widget/Cover_photo.php index d2eb1be92..af1ae5c7f 100644 --- a/Zotlabs/Widget/Cover_photo.php +++ b/Zotlabs/Widget/Cover_photo.php @@ -20,6 +20,16 @@ class Cover_photo { if(! $channel_id) return ''; + // only show cover photos once per login session + + if(array_key_exists('channels_visited',$_SESSION) && is_array($_SESSION['channels_visited']) && in_array($channel_id,$_SESSION['channels_visited'])) { + return EMPTY_STR; + } + if(! array_key_exists('channels_visited',$_SESSION)) { + $_SESSION['channels_visited'] = []; + } + $_SESSION['channels_visited'][] = $channel_id; + $channel = channelx_by_n($channel_id); if(array_key_exists('style', $arr) && isset($arr['style'])) -- cgit v1.2.3 From 9b620b2a35e256c905b6e3bd0e6f0228a0426e07 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 20 Aug 2018 20:07:54 -0700 Subject: remove checkjs reloader from mod_display also --- Zotlabs/Module/Display.php | 90 ++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 48 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index fe0408c6f..bdaed0933 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -21,8 +21,6 @@ class Display extends \Zotlabs\Web\Controller { $module_format = 'html'; } - $checkjs = new \Zotlabs\Web\CheckJS(1); - if($load) $_SESSION['loadtime'] = datetime_convert(); @@ -253,53 +251,44 @@ class Display extends \Zotlabs\Web\Controller { $sql_extra = public_permissions_sql($observer_hash); - if(($update && $load) || ($checkjs->disabled()) || ($module_format !== 'html')) { + if((! $update) || ($load)) { - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start'])); + $r = null; - if($load || ($checkjs->disabled()) || ($module_format !== 'html')) { + require_once('include/channel.php'); + $sys = get_sys_channel(); + $sysid = $sys['channel_id']; - $r = null; + if(local_channel()) { + $r = q("SELECT item.id as item_id from item WHERE uid = %d and mid = '%s' $item_normal limit 1", + intval(local_channel()), + dbesc($target_item['parent_mid']) + ); + if($r) { + $updateable = true; + } + } - require_once('include/channel.php'); - $sys = get_sys_channel(); - $sysid = $sys['channel_id']; + if(! $r) { - if(local_channel()) { - $r = q("SELECT item.id as item_id from item - WHERE uid = %d - and mid = '%s' - $item_normal - limit 1", - intval(local_channel()), - dbesc($target_item['parent_mid']) - ); - if($r) { - $updateable = true; - } - } + // in case somebody turned off public access to sys channel content using permissions + // make that content unsearchable by ensuring the owner uid can't match - if(! $r) { - - // in case somebody turned off public access to sys channel content using permissions - // make that content unsearchable by ensuring the owner uid can't match - - if(! perm_is_allowed($sysid,$observer_hash,'view_stream')) - $sysid = 0; - - $r = q("SELECT item.id as item_id from item - WHERE mid = '%s' - AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' - AND item.deny_gid = '' AND item_private = 0 ) - and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) - OR uid = %d ) - $sql_extra ) - $item_normal - limit 1", - dbesc($target_item['parent_mid']), - intval($sysid) - ); - } + if(! perm_is_allowed($sysid,$observer_hash,'view_stream')) + $sysid = 0; + + $r = q("SELECT item.id as item_id from item + WHERE mid = '%s' + AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = '' + AND item.deny_gid = '' AND item_private = 0 ) + and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " )) + OR uid = %d ) + $sql_extra ) + $item_normal + limit 1", + dbesc($target_item['parent_mid']), + intval($sysid) + ); } } @@ -373,14 +362,19 @@ class Display extends \Zotlabs\Web\Controller { case 'html': - if ($checkjs->disabled()) { + if ($update) { + $o .= conversation($items, 'display', $update, 'client'); + } + else { + $o .= ''; + if ($items[0]['title']) \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title']; - } - else { + $o .= conversation($items, 'display', $update, 'client'); - } + } break; @@ -435,7 +429,7 @@ class Display extends \Zotlabs\Web\Controller { $o .= '
'; - if((($update && $load) || $checkjs->disabled()) && (! $items)) { + if(((! $update) || ($load)) && (! $items)) { $r = q("SELECT id, item_deleted FROM item WHERE mid = '%s' LIMIT 1", dbesc($item_hash) -- cgit v1.2.3 From 8bf1e3a9449b95307d6d991284dce1addade813a Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 20 Aug 2018 22:02:08 -0700 Subject: more code optimisation --- Zotlabs/Module/Channel.php | 14 ++++++++------ Zotlabs/Module/Network.php | 22 ++++++++++++---------- 2 files changed, 20 insertions(+), 16 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index f1ae2f507..9d4c23e4c 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -2,21 +2,23 @@ namespace Zotlabs\Module; -use \App; -require_once('include/contact_widgets.php'); +use App; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\PermissionDescription; + require_once('include/items.php'); -require_once("include/bbcode.php"); require_once('include/security.php'); require_once('include/conversation.php'); require_once('include/acl_selectors.php'); -require_once('include/permissions.php'); + /** * @brief Channel Controller * */ -class Channel extends \Zotlabs\Web\Controller { + +class Channel extends Controller { function init() { @@ -151,7 +153,7 @@ class Channel extends \Zotlabs\Web\Controller { 'default_location' => (($is_owner) ? App::$profile['channel_location'] : ''), 'nickname' => App::$profile['channel_address'], 'lockstate' => (((strlen(App::$profile['channel_allow_cid'])) || (strlen(App::$profile['channel_allow_gid'])) || (strlen(App::$profile['channel_deny_cid'])) || (strlen(App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'), - 'acl' => (($is_owner) ? populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''), + 'acl' => (($is_owner) ? populate_acl($channel_acl,true, PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''), 'permissions' => $channel_acl, 'showacl' => (($is_owner) ? 'yes' : ''), 'bang' => '', diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 77a08585b..ca0ec7844 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -1,6 +1,8 @@ \App::$query_string); + $arr = array('query' => App::$query_string); call_hooks('network_content_init', $arr); - $channel = \App::get_channel(); + $channel = App::get_channel(); $item_normal = item_normal(); $item_normal_update = item_normal_update(); @@ -326,10 +328,10 @@ class Network extends \Zotlabs\Web\Controller { $o .= '
' . "\r\n"; $o .= "\r\n"; - \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( + App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array( '$baseurl' => z_root(), '$pgtype' => 'network', '$uid' => ((local_channel()) ? local_channel() : '0'), @@ -346,7 +348,7 @@ class Network extends \Zotlabs\Web\Controller { '$wall' => '0', '$static' => $static, '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), - '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), + '$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1), '$search' => (($search) ? $search : ''), '$xchan' => $xchan, '$order' => $order, @@ -417,8 +419,8 @@ class Network extends \Zotlabs\Web\Controller { } else { $itemspage = get_pconfig(local_channel(),'system','itemspage'); - \App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); } // cmin and cmax are both -1 when the affinity tool is disabled -- cgit v1.2.3 From 5d2ac10073cced796aaea5923aad76e82d01b2ed Mon Sep 17 00:00:00 2001 From: Mario Date: Tue, 21 Aug 2018 11:12:41 +0000 Subject: Merge branch 'patch-17' into 'master' Add missed app 'Order Apps' See merge request hubzilla/core!1258 (cherry picked from commit 85aa4957414c98fb6f44c0c2b79ef9d198e963a7) 6086a70e Add missed app 'Order Apps' --- Zotlabs/Lib/Apps.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 9027b13bc..1d9fe48e6 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -336,7 +336,8 @@ class Apps { 'Profile' => t('Profile'), 'Profiles' => t('Profiles'), 'Privacy Groups' => t('Privacy Groups'), - 'Notifications' => t('Notifications') + 'Notifications' => t('Notifications'), + 'Order Apps' => t('Order Apps') ); if(array_key_exists('name',$arr)) { -- cgit v1.2.3 From 42c4a0da51c61497427721a7467d1d6c8a09a605 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 21 Aug 2018 21:38:10 -0700 Subject: Zot/Finger: ignore deleted hublocs --- Zotlabs/Zot/Finger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Zot/Finger.php b/Zotlabs/Zot/Finger.php index 348171bdc..559f9657a 100644 --- a/Zotlabs/Zot/Finger.php +++ b/Zotlabs/Zot/Finger.php @@ -55,7 +55,7 @@ class Finger { $r = q("select xchan.*, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash - where xchan_addr = '%s' and hubloc_primary = 1 limit 1", + where xchan_addr = '%s' and hubloc_primary = 1 and hubloc_deleted = 0 limit 1", dbesc($xchan_addr) ); -- cgit v1.2.3 From 6ecd31a715c3d4fb5f2073f376cb9509bc6427d6 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 22 Aug 2018 13:30:16 -0700 Subject: tweak archive widget for articles --- Zotlabs/Module/Articles.php | 17 +++++++++++++++-- Zotlabs/Widget/Archive.php | 6 +++--- 2 files changed, 18 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index 284868241..e1f0b4ab0 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -51,6 +51,8 @@ class Articles extends \Zotlabs\Web\Controller { $sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY)); } + $datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : ''); + $datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : ''); $which = argv(1); @@ -143,10 +145,21 @@ class Articles extends \Zotlabs\Web\Controller { $sql_item = "and item.id = " . intval($r[0]['iid']) . " "; } } - + if($datequery) { + $sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery)))); + $order = 'post'; + } + if($datequery2) { + $sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2)))); + } + + if($datequery || $datequery2) { + $sql_extra2 .= " and item.item_thread_top != 0 "; + } + $r = q("select * from item where item.uid = %d and item_type = %d - $sql_extra $sql_item order by item.created desc $pager_sql", + $sql_extra $sql_extra2 $sql_item order by item.created desc $pager_sql", intval($owner), intval(ITEM_TYPE_ARTICLE) ); diff --git a/Zotlabs/Widget/Archive.php b/Zotlabs/Widget/Archive.php index c151ca563..9adaac38f 100644 --- a/Zotlabs/Widget/Archive.php +++ b/Zotlabs/Widget/Archive.php @@ -22,12 +22,12 @@ class Archive { return ''; $wall = ((array_key_exists('wall', $arr)) ? intval($arr['wall']) : 0); + $wall = ((array_key_exists('articles', $arr)) ? 2 : $wall); + $style = ((array_key_exists('style', $arr)) ? $arr['style'] : 'select'); $showend = ((get_pconfig($uid,'system','archive_show_end_date')) ? true : false); $mindate = get_pconfig($uid,'system','archive_mindate'); - $visible_years = get_pconfig($uid,'system','archive_visible_years'); - if(! $visible_years) - $visible_years = 5; + $visible_years = get_pconfig($uid,'system','archive_visible_years',5); $url = z_root() . '/' . \App::$cmd; -- cgit v1.2.3 From 2893f7d4810de99a989f7d36d041a120fafac029 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Thu, 23 Aug 2018 23:54:18 -0400 Subject: Get full page of items --- Zotlabs/Module/Network.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index ca0ec7844..9eedf113d 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -510,7 +510,7 @@ class Network extends \Zotlabs\Web\Controller { if($load) { // Fetch a page full of parent items for this page - $r = q("SELECT item.parent AS item_id FROM item + $r = q("SELECT DISTINCT(item.parent) AS item_id FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids $item_thread_top $item_normal @@ -524,7 +524,7 @@ class Network extends \Zotlabs\Web\Controller { else { // this is an update - $r = q("SELECT item.parent AS item_id FROM item + $r = q("SELECT DISTINCT(item.parent) AS item_id FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids $item_normal_update $simple_update -- cgit v1.2.3 From 67a9dd84975d4689a1046074f368cc0543100324 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sat, 25 Aug 2018 21:20:00 +0200 Subject: Update NativeWikiPage.php --- Zotlabs/Lib/NativeWikiPage.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php index 919c51276..f129217c5 100644 --- a/Zotlabs/Lib/NativeWikiPage.php +++ b/Zotlabs/Lib/NativeWikiPage.php @@ -556,7 +556,10 @@ class NativeWikiPage { '$pageHistory' => $pageHistory['history'], '$permsWrite' => $arr['permsWrite'], '$name_lbl' => t('Name'), - '$msg_label' => t('Message','wiki_history') + '$msg_label' => t('Message','wiki_history'), + '$date_lbl' => t('Date'), + '$revert_btn' => t('Revert'), + '$compare_btn' => t('Compare') )); } @@ -692,4 +695,4 @@ class NativeWikiPage { return $o; } -} +} \ No newline at end of file -- cgit v1.2.3 From 308dda1587bc175cab41bc4a02dae8ec568668b3 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sat, 25 Aug 2018 21:21:57 +0200 Subject: Update Wiki.php --- Zotlabs/Module/Wiki.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 322a3933c..548a83c22 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -384,6 +384,8 @@ class Wiki extends \Zotlabs\Web\Controller { '$modalerrorlist' => t('Error getting album list'), '$modalerrorlink' => t('Error getting photo link'), '$modalerroralbum' => t('Error getting album'), + '$view_lbl' => t('View'), + '$history_lbl' => t('History') )); if($p['pageMimeType'] === 'text/markdown') -- cgit v1.2.3 From 88ebcb56e7d1f70a594f3f11b0d209e084a3521a Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sat, 25 Aug 2018 21:23:08 +0200 Subject: Update Wiki_page_history.php --- Zotlabs/Widget/Wiki_page_history.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Wiki_page_history.php b/Zotlabs/Widget/Wiki_page_history.php index dcec9a037..0f865f12d 100644 --- a/Zotlabs/Widget/Wiki_page_history.php +++ b/Zotlabs/Widget/Wiki_page_history.php @@ -20,7 +20,10 @@ class Wiki_page_history { '$pageHistory' => $pageHistory['history'], '$permsWrite' => $arr['permsWrite'], '$name_lbl' => t('Name'), - '$msg_label' => t('Message','wiki_history') + '$msg_label' => t('Message','wiki_history'), + '$date_lbl' => t('Date'), + '$revert_btn' => t('Revert'), + '$compare_btn' => t('Compare') )); } -- cgit v1.2.3 From e78a4d61d85bac570a63086ec1af68eee3c9c9b0 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sat, 25 Aug 2018 21:25:26 +0200 Subject: Update NativeWikiPage.php --- Zotlabs/Lib/NativeWikiPage.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php index f129217c5..d4875bbaf 100644 --- a/Zotlabs/Lib/NativeWikiPage.php +++ b/Zotlabs/Lib/NativeWikiPage.php @@ -557,9 +557,9 @@ class NativeWikiPage { '$permsWrite' => $arr['permsWrite'], '$name_lbl' => t('Name'), '$msg_label' => t('Message','wiki_history'), - '$date_lbl' => t('Date'), - '$revert_btn' => t('Revert'), - '$compare_btn' => t('Compare') + '$date_lbl' => t('Date'), + '$revert_btn' => t('Revert'), + '$compare_btn' => t('Compare') )); } @@ -695,4 +695,4 @@ class NativeWikiPage { return $o; } -} \ No newline at end of file +} -- cgit v1.2.3 From c9b80a3612755628cbb6af57458006dd39cf0f5f Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sat, 25 Aug 2018 21:26:50 +0200 Subject: Update Wiki.php --- Zotlabs/Module/Wiki.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 548a83c22..25ecb6a6a 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -384,8 +384,8 @@ class Wiki extends \Zotlabs\Web\Controller { '$modalerrorlist' => t('Error getting album list'), '$modalerrorlink' => t('Error getting photo link'), '$modalerroralbum' => t('Error getting album'), - '$view_lbl' => t('View'), - '$history_lbl' => t('History') + '$view_lbl' => t('View'), + '$history_lbl' => t('History') )); if($p['pageMimeType'] === 'text/markdown') -- cgit v1.2.3 From 42c5e986707ffaa660b4fda9f23edbae9a3cb639 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sat, 25 Aug 2018 21:27:20 +0200 Subject: Update Wiki_page_history.php --- Zotlabs/Widget/Wiki_page_history.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Wiki_page_history.php b/Zotlabs/Widget/Wiki_page_history.php index 0f865f12d..dbb322dc3 100644 --- a/Zotlabs/Widget/Wiki_page_history.php +++ b/Zotlabs/Widget/Wiki_page_history.php @@ -21,9 +21,9 @@ class Wiki_page_history { '$permsWrite' => $arr['permsWrite'], '$name_lbl' => t('Name'), '$msg_label' => t('Message','wiki_history'), - '$date_lbl' => t('Date'), - '$revert_btn' => t('Revert'), - '$compare_btn' => t('Compare') + '$date_lbl' => t('Date'), + '$revert_btn' => t('Revert'), + '$compare_btn' => t('Compare') )); } -- cgit v1.2.3 From a0c2bbac9d96a5461b65b5e0ff733a2fcd193dd4 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Sun, 26 Aug 2018 23:26:10 -0400 Subject: Add hook to extend conv_item cog dropdown menu --- Zotlabs/Lib/ThreadItem.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index ed78ae00b..f8a7366f8 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -325,6 +325,10 @@ class ThreadItem { $has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false); + $dropdown_extras_arr = [ 'item' => $item , 'dropdown_extras' => '' ]; + call_hooks('dropdown_extras',$dropdown_extras_arr); + $dropdown_extras = $dropdown_extras_arr['dropdown_extras']; + $tmp_item = array( 'template' => $this->get_template(), 'mode' => $mode, @@ -404,6 +408,7 @@ class ThreadItem { 'addtocal' => (($has_event) ? t('Add to Calendar') : ''), 'drop' => $drop, 'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''), + 'dropdown_extras' => $dropdown_extras, // end toolbar buttons 'unseen_comments' => $unseen_comments, -- cgit v1.2.3 From 9367e9fe5a0125bf4c2f77909f2789c9dcd41e1e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 26 Aug 2018 23:00:31 -0700 Subject: Change main router request variable from 'q' to 'req'. This is necessary to implement search in the twitter api addon, because twitter requires use of the variable 'q'. --- Zotlabs/Lib/Libzotdir.php | 2 +- Zotlabs/Module/Connections.php | 2 +- Zotlabs/Module/Directory.php | 2 +- Zotlabs/Module/Photos.php | 4 ++-- Zotlabs/Module/Rpost.php | 2 +- Zotlabs/Module/Viewconnections.php | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzotdir.php b/Zotlabs/Lib/Libzotdir.php index 91d089c86..81a5b3319 100644 --- a/Zotlabs/Lib/Libzotdir.php +++ b/Zotlabs/Lib/Libzotdir.php @@ -152,7 +152,7 @@ class Libzotdir { unset($tmp['pubforums']); unset($tmp['global']); unset($tmp['safe']); - unset($tmp['q']); + unset($tmp['req']); unset($tmp['f']); $forumsurl = $url . http_build_query($tmp) . $suggest; diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index cecada769..48b59cb8c 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -326,7 +326,7 @@ class Connections extends \Zotlabs\Web\Controller { killme(); } else { - $o .= ""; + $o .= ""; $o .= replace_macros(get_markup_template('connections.tpl'),array( '$header' => t('Connections') . (($head) ? ': ' . $head : ''), '$tabs' => $tabs, diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php index 8a7c6baf6..59b832a0f 100644 --- a/Zotlabs/Module/Directory.php +++ b/Zotlabs/Module/Directory.php @@ -395,7 +395,7 @@ class Directory extends \Zotlabs\Web\Controller { $dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory')); - $o .= ""; + $o .= ""; $o .= replace_macros($tpl, array( '$search' => $search, '$desc' => t('Find'), diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 489bffc4a..d3ef8d60b 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -838,7 +838,7 @@ class Photos extends \Zotlabs\Web\Controller { killme(); } else { - $o .= ""; + $o .= ""; $tpl = get_markup_template('photo_album.tpl'); $o .= replace_macros($tpl, array( '$photos' => $photos, @@ -1377,7 +1377,7 @@ class Photos extends \Zotlabs\Web\Controller { killme(); } else { - $o .= ""; + $o .= ""; $tpl = get_markup_template('photos_recent.tpl'); $o .= replace_macros($tpl, array( '$title' => t('Recent Photos'), diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php index 86ee296ec..50d1ec2aa 100644 --- a/Zotlabs/Module/Rpost.php +++ b/Zotlabs/Module/Rpost.php @@ -46,7 +46,7 @@ class Rpost extends \Zotlabs\Web\Controller { // make sure we're not looping to our own hub if(($url) && (! stristr($url, \App::get_hostname()))) { foreach($_GET as $key => $arg) { - if($key === 'q') + if($key === 'req') continue; $url .= '&' . $key . '=' . $arg; } diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php index 0a5e86907..223e185e1 100644 --- a/Zotlabs/Module/Viewconnections.php +++ b/Zotlabs/Module/Viewconnections.php @@ -107,7 +107,7 @@ class Viewconnections extends \Zotlabs\Web\Controller { killme(); } else { - $o .= ""; + $o .= ""; $tpl = get_markup_template("viewcontact_template.tpl"); $o .= replace_macros($tpl, array( '$title' => t('View Connections'), -- cgit v1.2.3 From e4b6a143c7679428ecf7208274fddb5f1b37c70e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 26 Aug 2018 23:05:56 -0700 Subject: Revert "Change main router request variable from 'q' to 'req'. This is necessary to implement search in the twitter api addon, because twitter requires use of the variable 'q'." Reverting because this will only work with Apache and break nginx/other installations. This reverts commit 9367e9fe5a0125bf4c2f77909f2789c9dcd41e1e. --- Zotlabs/Lib/Libzotdir.php | 2 +- Zotlabs/Module/Connections.php | 2 +- Zotlabs/Module/Directory.php | 2 +- Zotlabs/Module/Photos.php | 4 ++-- Zotlabs/Module/Rpost.php | 2 +- Zotlabs/Module/Viewconnections.php | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libzotdir.php b/Zotlabs/Lib/Libzotdir.php index 81a5b3319..91d089c86 100644 --- a/Zotlabs/Lib/Libzotdir.php +++ b/Zotlabs/Lib/Libzotdir.php @@ -152,7 +152,7 @@ class Libzotdir { unset($tmp['pubforums']); unset($tmp['global']); unset($tmp['safe']); - unset($tmp['req']); + unset($tmp['q']); unset($tmp['f']); $forumsurl = $url . http_build_query($tmp) . $suggest; diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index 48b59cb8c..cecada769 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -326,7 +326,7 @@ class Connections extends \Zotlabs\Web\Controller { killme(); } else { - $o .= ""; + $o .= ""; $o .= replace_macros(get_markup_template('connections.tpl'),array( '$header' => t('Connections') . (($head) ? ': ' . $head : ''), '$tabs' => $tabs, diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php index 59b832a0f..8a7c6baf6 100644 --- a/Zotlabs/Module/Directory.php +++ b/Zotlabs/Module/Directory.php @@ -395,7 +395,7 @@ class Directory extends \Zotlabs\Web\Controller { $dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory')); - $o .= ""; + $o .= ""; $o .= replace_macros($tpl, array( '$search' => $search, '$desc' => t('Find'), diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index d3ef8d60b..489bffc4a 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -838,7 +838,7 @@ class Photos extends \Zotlabs\Web\Controller { killme(); } else { - $o .= ""; + $o .= ""; $tpl = get_markup_template('photo_album.tpl'); $o .= replace_macros($tpl, array( '$photos' => $photos, @@ -1377,7 +1377,7 @@ class Photos extends \Zotlabs\Web\Controller { killme(); } else { - $o .= ""; + $o .= ""; $tpl = get_markup_template('photos_recent.tpl'); $o .= replace_macros($tpl, array( '$title' => t('Recent Photos'), diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php index 50d1ec2aa..86ee296ec 100644 --- a/Zotlabs/Module/Rpost.php +++ b/Zotlabs/Module/Rpost.php @@ -46,7 +46,7 @@ class Rpost extends \Zotlabs\Web\Controller { // make sure we're not looping to our own hub if(($url) && (! stristr($url, \App::get_hostname()))) { foreach($_GET as $key => $arg) { - if($key === 'req') + if($key === 'q') continue; $url .= '&' . $key . '=' . $arg; } diff --git a/Zotlabs/Module/Viewconnections.php b/Zotlabs/Module/Viewconnections.php index 223e185e1..0a5e86907 100644 --- a/Zotlabs/Module/Viewconnections.php +++ b/Zotlabs/Module/Viewconnections.php @@ -107,7 +107,7 @@ class Viewconnections extends \Zotlabs\Web\Controller { killme(); } else { - $o .= ""; + $o .= ""; $tpl = get_markup_template("viewcontact_template.tpl"); $o .= replace_macros($tpl, array( '$title' => t('View Connections'), -- cgit v1.2.3 From 6a2bbed73dfb34975c4525c34c03f20c6945dedc Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 27 Aug 2018 10:19:10 +0200 Subject: remove distinct from network query again until performance issue is resolved or another fix for the underlying problem is found --- Zotlabs/Module/Network.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 9eedf113d..ca0ec7844 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -510,7 +510,7 @@ class Network extends \Zotlabs\Web\Controller { if($load) { // Fetch a page full of parent items for this page - $r = q("SELECT DISTINCT(item.parent) AS item_id FROM item + $r = q("SELECT item.parent AS item_id FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids $item_thread_top $item_normal @@ -524,7 +524,7 @@ class Network extends \Zotlabs\Web\Controller { else { // this is an update - $r = q("SELECT DISTINCT(item.parent) AS item_id FROM item + $r = q("SELECT item.parent AS item_id FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids $item_normal_update $simple_update -- cgit v1.2.3 From 7ecb337405aa1ca9327487eecaa352059ee65052 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 28 Aug 2018 22:43:37 -0700 Subject: redirect stdout/stderr on cron command --- Zotlabs/Daemon/Notifier.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index fa2368a92..f74c8f11c 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -559,6 +559,8 @@ class Notifier { foreach($dhubs as $hub) { + logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG); + if($hub['hubloc_network'] !== 'zot') { $narr = [ 'channel' => $channel, -- cgit v1.2.3 From 42093aedcf9af8433ad9764116b98182e4fba658 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 29 Aug 2018 13:57:36 +0200 Subject: db update to get rid of bogus activitypub xchans which got created due to a bug in the pubcrawl addon --- Zotlabs/Update/_1219.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Zotlabs/Update/_1219.php (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1219.php b/Zotlabs/Update/_1219.php new file mode 100644 index 000000000..be2534001 --- /dev/null +++ b/Zotlabs/Update/_1219.php @@ -0,0 +1,26 @@ + Date: Fri, 31 Aug 2018 20:26:31 +0200 Subject: update 1218: missing default value for pg --- Zotlabs/Update/_1218.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1218.php b/Zotlabs/Update/_1218.php index 67d8b49a5..07c7dba20 100644 --- a/Zotlabs/Update/_1218.php +++ b/Zotlabs/Update/_1218.php @@ -7,9 +7,9 @@ class _1218 { function run() { if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { - $r1 = q("ALTER TABLE hubloc add hubloc_id_url text NOT NULL"); + $r1 = q("ALTER TABLE hubloc add hubloc_id_url text NOT NULL DEFAULT ''"); $r2 = q("create index \"hubloc_id_url\" on hubloc (\"hubloc_id_url\")"); - $r3 = q("ALTER TABLE hubloc add hubloc_site_id text NOT NULL"); + $r3 = q("ALTER TABLE hubloc add hubloc_site_id text NOT NULL DEFAULT ''"); $r4 = q("create index \"hubloc_site_id\" on hubloc (\"hubloc_site_id\")"); $r = $r1 && $r2 && $r3 && $r4; -- cgit v1.2.3 From 4376f8f030ea36fd5fed263efcee3a5276af0da1 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 1 Sep 2018 13:43:32 +0200 Subject: do not count sys channel in totals --- 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 2df8dc25d..6edced9b5 100644 --- a/Zotlabs/Module/Admin.php +++ b/Zotlabs/Module/Admin.php @@ -109,7 +109,7 @@ class Admin extends \Zotlabs\Web\Controller { // available channels, primary and clones $channels = array(); - $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0"); + $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0 and channel_system = 0"); if ($r) { $channels['total'] = array('label' => t('Channels'), 'val' => $r[0]['total']); $channels['main'] = array('label' => t('Primary'), 'val' => $r[0]['main']); -- cgit v1.2.3 From e2824f925964fbfe160255de6e733b4c2de3cecb Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Sat, 1 Sep 2018 13:45:05 -0400 Subject: Fix: Authors unable to comment on posts they authored when under owned by others in certain circumstances. --- Zotlabs/Module/Item.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 640b4fa5c..a24d6da9c 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -29,7 +29,7 @@ use \Zotlabs\Lib as Zlib; class Item extends \Zotlabs\Web\Controller { function post() { - + // This will change. Figure out who the observer is and whether or not // they have permission to post here. Else ignore the post. @@ -237,10 +237,12 @@ class Item extends \Zotlabs\Web\Controller { if($parent) { logger('mod_item: item_post parent=' . $parent); $can_comment = false; - if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self'])) - $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments'); - else - $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item); + + $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item); + if (!$can_comment) { + if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self'])==1 ) + $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments'); + } if(! $can_comment) { notice( t('Permission denied.') . EOL) ; -- cgit v1.2.3 From d66f58a550d61f17c46eca42cba84f45ae9c4628 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 1 Sep 2018 21:09:04 +0200 Subject: fix undefined constant warning --- Zotlabs/Module/Filestorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Filestorage.php b/Zotlabs/Module/Filestorage.php index cd9ab601d..23bd63f95 100644 --- a/Zotlabs/Module/Filestorage.php +++ b/Zotlabs/Module/Filestorage.php @@ -128,7 +128,7 @@ class Filestorage extends \Zotlabs\Web\Controller { } } - if(json_return) + if($json_return) json_return_and_die([ 'success' => true ]); goaway(dirname($url)); -- cgit v1.2.3 From 41ccb61c2e2f2123ae510a39ebd048a56832825e Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 3 Sep 2018 18:14:17 +0200 Subject: Revert "Fix: Authors unable to comment on posts they authored when under owned by others in certain circumstances." This reverts commit e2824f925964fbfe160255de6e733b4c2de3cecb. Reverting because it breaks forum mentions. --- Zotlabs/Module/Item.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index a24d6da9c..640b4fa5c 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -29,7 +29,7 @@ use \Zotlabs\Lib as Zlib; class Item extends \Zotlabs\Web\Controller { function post() { - + // This will change. Figure out who the observer is and whether or not // they have permission to post here. Else ignore the post. @@ -237,12 +237,10 @@ class Item extends \Zotlabs\Web\Controller { if($parent) { logger('mod_item: item_post parent=' . $parent); $can_comment = false; - - $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item); - if (!$can_comment) { - if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self'])==1 ) - $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments'); - } + if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self'])) + $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments'); + else + $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item); if(! $can_comment) { notice( t('Permission denied.') . EOL) ; -- cgit v1.2.3 From 9446e0348efa151ef7d75fa8206bb578633273dd Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Tue, 4 Sep 2018 07:54:24 -0400 Subject: Corrected resubmit of fixes to Authors unable to comment on posts they authored when owned by others. --- Zotlabs/Module/Item.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 640b4fa5c..a24d6da9c 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -29,7 +29,7 @@ use \Zotlabs\Lib as Zlib; class Item extends \Zotlabs\Web\Controller { function post() { - + // This will change. Figure out who the observer is and whether or not // they have permission to post here. Else ignore the post. @@ -237,10 +237,12 @@ class Item extends \Zotlabs\Web\Controller { if($parent) { logger('mod_item: item_post parent=' . $parent); $can_comment = false; - if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self'])) - $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments'); - else - $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item); + + $can_comment = can_comment_on_post($observer['xchan_hash'],$parent_item); + if (!$can_comment) { + if((array_key_exists('owner',$parent_item)) && intval($parent_item['owner']['abook_self'])==1 ) + $can_comment = perm_is_allowed($profile_uid,$observer['xchan_hash'],'post_comments'); + } if(! $can_comment) { notice( t('Permission denied.') . EOL) ; -- cgit v1.2.3 From a821682c8c165077947781bca2064922884f6e7d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 5 Sep 2018 12:17:32 +0200 Subject: instead of not displaying the cover-photo at all after first page load, load the page with the cover slided up. change pointer to n-resize if cover is not slid. --- Zotlabs/Widget/Cover_photo.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Cover_photo.php b/Zotlabs/Widget/Cover_photo.php index af1ae5c7f..965566523 100644 --- a/Zotlabs/Widget/Cover_photo.php +++ b/Zotlabs/Widget/Cover_photo.php @@ -21,9 +21,9 @@ class Cover_photo { return ''; // only show cover photos once per login session - + $hide_cover = false; if(array_key_exists('channels_visited',$_SESSION) && is_array($_SESSION['channels_visited']) && in_array($channel_id,$_SESSION['channels_visited'])) { - return EMPTY_STR; + $hide_cover = true; } if(! array_key_exists('channels_visited',$_SESSION)) { $_SESSION['channels_visited'] = []; @@ -53,6 +53,7 @@ class Cover_photo { $subtitle = str_replace('@','@',$channel['xchan_addr']); $c = get_cover_photo($channel_id,'html'); + $c = str_replace('src=', 'data-src=', $c); if($c) { $photo_html = (($style) ? str_replace('alt=',' style="' . $style . '" alt=',$c) : $c); @@ -62,6 +63,7 @@ class Cover_photo { '$title' => $title, '$subtitle' => $subtitle, '$hovertitle' => t('Click to show more'), + '$hide_cover' => $hide_cover )); } return $o; -- cgit v1.2.3 From ea381d918021a33a73df40de95fd0c57f0edc5c2 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 5 Sep 2018 14:44:06 +0200 Subject: move str_replace inside if clause --- Zotlabs/Widget/Cover_photo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Cover_photo.php b/Zotlabs/Widget/Cover_photo.php index 965566523..955048992 100644 --- a/Zotlabs/Widget/Cover_photo.php +++ b/Zotlabs/Widget/Cover_photo.php @@ -53,9 +53,9 @@ class Cover_photo { $subtitle = str_replace('@','@',$channel['xchan_addr']); $c = get_cover_photo($channel_id,'html'); - $c = str_replace('src=', 'data-src=', $c); if($c) { + $c = str_replace('src=', 'data-src=', $c); $photo_html = (($style) ? str_replace('alt=',' style="' . $style . '" alt=',$c) : $c); $o = replace_macros(get_markup_template('cover_photo_widget.tpl'),array( -- cgit v1.2.3 From bb42ec2bfc0826dde3e3915566c4689762b128d7 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 7 Sep 2018 10:39:15 +0200 Subject: apps: change page title to available/installed, display install action label in button and use different icons for installable and updateable apps --- Zotlabs/Lib/Apps.php | 3 ++- Zotlabs/Module/Apps.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 1d9fe48e6..860a799ef 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -500,7 +500,8 @@ class Apps { '$icon' => $icon, '$hosturl' => $hosturl, '$purchase' => (($papp['page'] && (! $installed)) ? t('Purchase') : ''), - '$install' => (($hosturl && in_array($mode, ['view','install'])) ? $install_action : ''), + '$installed' => $installed, + '$action_label' => (($hosturl && in_array($mode, ['view','install'])) ? $install_action : ''), '$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''), '$delete' => ((local_channel() && $installed && $mode == 'edit') ? t('Delete') : ''), '$undelete' => ((local_channel() && $installed && $mode == 'edit') ? t('Undelete') : ''), diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php index 78c8d99ae..11025ce6e 100644 --- a/Zotlabs/Module/Apps.php +++ b/Zotlabs/Module/Apps.php @@ -47,7 +47,7 @@ class Apps extends \Zotlabs\Web\Controller { return replace_macros(get_markup_template('myapps.tpl'), array( '$sitename' => get_config('system','sitename'), '$cat' => $cat, - '$title' => t('Apps'), + '$title' => (($available) ? t('Available Apps') : t('Installed Apps')), '$apps' => $apps, '$authed' => ((local_channel()) ? true : false), '$manage' => (($available) ? '' : t('Manage apps')), -- cgit v1.2.3 From 54fa28441c5f0bdcd9687615f4a6b7a0fab024a3 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 7 Sep 2018 11:26:02 +0200 Subject: install bootstrap via composer --- Zotlabs/Render/Comanche.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Render/Comanche.php b/Zotlabs/Render/Comanche.php index f58dba60e..cf87cc7d7 100644 --- a/Zotlabs/Render/Comanche.php +++ b/Zotlabs/Render/Comanche.php @@ -441,7 +441,7 @@ class Comanche { $path = 'view/js/jquery.js'; break; case 'bootstrap': - $path = 'library/bootstrap/js/bootstrap.min.js'; + $path = 'vendor/twbs/bootstrap/dist/js/bootstrap.bundle.min.js'; break; case 'foundation': $path = 'library/foundation/js/foundation.js'; @@ -466,7 +466,7 @@ class Comanche { switch($s) { case 'bootstrap': - $path = 'library/bootstrap/css/bootstrap.min.css'; + $path = 'vendor/twbs/bootstrap/dist/css/bootstrap.min.css'; break; case 'foundation': $path = 'library/foundation/css/foundation.min.css'; -- cgit v1.2.3 From d29415a6e2f1b89e7e9463ce337946d7bf78aa5c Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 7 Sep 2018 14:23:16 +0200 Subject: provide a noscript_content switch for mod channel and display --- Zotlabs/Module/Channel.php | 15 ++++++++++++--- Zotlabs/Module/Display.php | 14 ++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 9d4c23e4c..dff44660c 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -71,6 +71,8 @@ class Channel extends Controller { function get($update = 0, $load = false) { + $noscript_content = get_config('system', 'noscript_content', '1'); + if($load) $_SESSION['loadtime'] = datetime_convert(); @@ -272,7 +274,7 @@ class Channel extends Controller { App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); - if((! $update) || ($load)) { + if($noscript_content || $load) { if($mid) { $r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal AND item_wall = 1 $sql_extra limit 1", @@ -411,10 +413,17 @@ class Channel extends Controller { $o .= conversation($items,$mode,$update,$page_mode); } else { + $o .= ''; + $o .= conversation($items,$mode,$update,$page_mode); if ($mid && $items[0]['title']) diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index bdaed0933..1d21b64ac 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -12,8 +12,9 @@ class Display extends \Zotlabs\Web\Controller { function get($update = 0, $load = false) { - $module_format = 'html'; + $noscript_content = get_config('system', 'noscript_content', '1'); + $module_format = 'html'; if(argc() > 1) { $module_format = substr(argv(1),strrpos(argv(1),'.') + 1); @@ -251,7 +252,7 @@ class Display extends \Zotlabs\Web\Controller { $sql_extra = public_permissions_sql($observer_hash); - if((! $update) || ($load)) { + if($noscript_content || $load) { $r = null; @@ -367,7 +368,12 @@ class Display extends \Zotlabs\Web\Controller { } else { $o .= ''; if ($items[0]['title']) @@ -429,7 +435,7 @@ class Display extends \Zotlabs\Web\Controller { $o .= '
'; - if(((! $update) || ($load)) && (! $items)) { + if((($update && $load) || $noscript_content) && (! $items)) { $r = q("SELECT id, item_deleted FROM item WHERE mid = '%s' LIMIT 1", dbesc($item_hash) -- cgit v1.2.3 From 9607bb29fd354245f915fcf8c2d109035dc52ede Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 7 Sep 2018 14:58:16 +0200 Subject: missing text --- Zotlabs/Module/Channel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index dff44660c..8941faf56 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -420,7 +420,7 @@ class Channel extends Controller { $o .= alt_pager(count($items)); } else { - $o .= '
' . t('You must enable javascript for your browser to view this content.') . '
'; + $o .= '
' . t('You must enable javascript for your browser to be able to view this content.') . '
'; } $o .= ''; -- cgit v1.2.3 From be3b6304742a6c39d73674b1f7422c029e7cd804 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 9 Sep 2018 20:53:20 -0700 Subject: important hyperdrive component --- Zotlabs/Update/_1220.php | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Zotlabs/Update/_1220.php (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1220.php b/Zotlabs/Update/_1220.php new file mode 100644 index 000000000..adcb8c9c6 --- /dev/null +++ b/Zotlabs/Update/_1220.php @@ -0,0 +1,47 @@ + Date: Mon, 10 Sep 2018 13:34:05 +0200 Subject: move cards from features to apps --- Zotlabs/Module/Cards.php | 40 +++++++++++++++++++++++----------------- Zotlabs/Widget/Categories.php | 13 ++++++++----- 2 files changed, 31 insertions(+), 22 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index f196988a2..f81d9324f 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -1,12 +1,16 @@ Cards App - Not Installed:
'; + $o .= 'Create personal planning cards'; + return $o; } - nav_set_selected(t('Cards')); + nav_set_selected('Cards'); head_add_link([ 'rel' => 'alternate', 'type' => 'application/json+oembed', - 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string), 'title' => 'oembed' ]); @@ -52,7 +58,7 @@ class Cards extends \Zotlabs\Web\Controller { $category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : ''); if($category) { - $sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY)); + $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY)); } @@ -60,11 +66,11 @@ class Cards extends \Zotlabs\Web\Controller { $selected_card = ((argc() > 2) ? argv(2) : ''); - $_SESSION['return_url'] = \App::$query_string; + $_SESSION['return_url'] = App::$query_string; $uid = local_channel(); - $owner = \App::$profile_uid; - $observer = \App::get_observer(); + $owner = App::$profile_uid; + $observer = App::get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); @@ -101,8 +107,8 @@ class Cards extends \Zotlabs\Web\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, - \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''), + 'acl' => (($is_owner) ? populate_acl($channel_acl, false, + PermissionDescription::fromGlobalPermission('view_pages')) : ''), 'permissions' => $channel_acl, 'showacl' => (($is_owner) ? true : false), 'visitor' => true, @@ -132,8 +138,8 @@ class Cards extends \Zotlabs\Web\Controller { $itemspage = get_pconfig(local_channel(),'system','itemspage'); - \App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); $sql_extra = item_permissions_sql($owner); @@ -171,7 +177,7 @@ class Cards extends \Zotlabs\Web\Controller { WHERE item.uid = %d $item_normal AND item.parent IN ( %s ) $sql_extra $sql_extra2 ", - intval(\App::$profile['profile_uid']), + intval(App::$profile['profile_uid']), dbesc($parents_str) ); if($items) { diff --git a/Zotlabs/Widget/Categories.php b/Zotlabs/Widget/Categories.php index 9bfa9742a..27d4b5980 100644 --- a/Zotlabs/Widget/Categories.php +++ b/Zotlabs/Widget/Categories.php @@ -2,6 +2,9 @@ namespace Zotlabs\Widget; +use App; +use Zotlabs\Lib\Apps; + require_once('include/contact_widgets.php'); class Categories { @@ -10,22 +13,22 @@ class Categories { $cards = ((array_key_exists('cards',$arr) && $arr['cards']) ? true : false); - if(($cards) && (! feature_enabled(\App::$profile['profile_uid'],'cards'))) + if(($cards) && (! Apps::system_app_installed(App::$profile['profile_uid'], 'Cards'))) return ''; $articles = ((array_key_exists('articles',$arr) && $arr['articles']) ? true : false); - if(($articles) && (! feature_enabled(\App::$profile['profile_uid'],'articles'))) + if(($articles) && (! feature_enabled(App::$profile['profile_uid'],'articles'))) return ''; - if((! \App::$profile['profile_uid']) - || (! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),(($cards || $articles) ? 'view_pages' : 'view_stream')))) { + if((! App::$profile['profile_uid']) + || (! perm_is_allowed(App::$profile['profile_uid'],get_observer_hash(),(($cards || $articles) ? 'view_pages' : 'view_stream')))) { return ''; } $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : ''); - $srchurl = (($cards) ? \App::$argv[0] . '/' . \App::$argv[1] : \App::$query_string); + $srchurl = (($cards) ? App::$argv[0] . '/' . App::$argv[1] : App::$query_string); $srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&'); $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); -- cgit v1.2.3 From 28e4977c33e11e4bb65c85977c82f3523f685bac Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 11 Sep 2018 11:16:58 +0200 Subject: include item.title in /network and /channel search --- Zotlabs/Module/Channel.php | 3 ++- Zotlabs/Module/Network.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 8941faf56..74fdc1cb4 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -197,7 +197,8 @@ class Channel extends Controller { $sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG); } else { - $sql_extra .= sprintf(" AND item.body like '%s' ", + $sql_extra .= sprintf(" AND (item.body like '%s' OR item.title like '%s') ", + dbesc(protect_sprintf('%' . $search . '%')), dbesc(protect_sprintf('%' . $search . '%')) ); } diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index ca0ec7844..c3db15ef2 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -382,7 +382,8 @@ class Network extends \Zotlabs\Web\Controller { $sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG); } else { - $sql_extra .= sprintf(" AND item.body like '%s' ", + $sql_extra .= sprintf(" AND (item.body like '%s' OR item.title like '%s') ", + dbesc(protect_sprintf('%' . $search . '%')), dbesc(protect_sprintf('%' . $search . '%')) ); } -- cgit v1.2.3 From 2651eae663869e78aa0166bd33ac80a44b26b5ea Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 12 Sep 2018 11:08:53 +0200 Subject: mpre feature to app transition --- Zotlabs/Module/Articles.php | 38 ++++++++----- Zotlabs/Module/Cards.php | 7 ++- Zotlabs/Module/Webpages.php | 55 ++++++++++++------- Zotlabs/Module/Wiki.php | 131 +++++++++++++++++++++++--------------------- Zotlabs/Widget/Appstore.php | 6 +- 5 files changed, 137 insertions(+), 100 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index e1f0b4ab0..d622b221a 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -1,12 +1,17 @@ Articles App (Not Installed):
'; + $o .= t('Create interactive articles'); + return $o; } nav_set_selected(t('Articles')); @@ -40,7 +50,7 @@ class Articles extends \Zotlabs\Web\Controller { head_add_link([ 'rel' => 'alternate', 'type' => 'application/json+oembed', - 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string), 'title' => 'oembed' ]); @@ -48,7 +58,7 @@ class Articles extends \Zotlabs\Web\Controller { $category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : ''); if($category) { - $sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY)); + $sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY)); } $datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : ''); @@ -58,11 +68,11 @@ class Articles extends \Zotlabs\Web\Controller { $selected_card = ((argc() > 2) ? argv(2) : ''); - $_SESSION['return_url'] = \App::$query_string; + $_SESSION['return_url'] = App::$query_string; $uid = local_channel(); - $owner = \App::$profile_uid; - $observer = \App::get_observer(); + $owner = App::$profile_uid; + $observer = App::get_observer(); $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); @@ -100,7 +110,7 @@ class Articles extends \Zotlabs\Web\Controller { '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, - \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''), + PermissionDescription::fromGlobalPermission('view_pages')) : ''), 'permissions' => $channel_acl, 'showacl' => (($is_owner) ? true : false), 'visitor' => true, @@ -130,8 +140,8 @@ class Articles extends \Zotlabs\Web\Controller { } $itemspage = get_pconfig(local_channel(),'system','itemspage'); - \App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start'])); + App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start'])); $sql_extra = item_permissions_sql($owner); @@ -179,7 +189,7 @@ class Articles extends \Zotlabs\Web\Controller { WHERE item.uid = %d $item_normal AND item.parent IN ( %s ) $sql_extra $sql_extra2 ", - intval(\App::$profile['profile_uid']), + intval(App::$profile['profile_uid']), dbesc($parents_str) ); if($items) { diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index f81d9324f..78cbad5fd 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -40,8 +40,11 @@ class Cards extends Controller { } if(! Apps::system_app_installed(App::$profile_uid, 'Cards')) { - $o = 'Cards App - Not Installed:
'; - $o .= 'Create personal planning cards'; + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'Cards App (Not Installed):
'; + $o .= t('Create personal planning cards'); return $o; } diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index 97ec55ba3..991c5ee71 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -1,19 +1,25 @@ 1 && argv(1) === 'sys' && is_site_admin()) { $sys = get_sys_channel(); if($sys && intval($sys['channel_id'])) { - \App::$is_sys = true; + App::$is_sys = true; } } @@ -29,23 +35,32 @@ class Webpages extends \Zotlabs\Web\Controller { function get() { - if(! \App::$profile) { + if(! App::$profile) { notice( t('Requested profile is not available.') . EOL ); - \App::$error = 404; + App::$error = 404; return; } + if(! Apps::system_app_installed(App::$profile_uid, 'Webpages')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'Webpages App (Not Installed):
'; + $o .= t('Provide managed web pages on your channel'); + return $o; + } + nav_set_selected('Webpages'); $which = argv(1); - $_SESSION['return_url'] = \App::$query_string; + $_SESSION['return_url'] = App::$query_string; $uid = local_channel(); $owner = 0; - $observer = \App::get_observer(); + $observer = App::get_observer(); - $channel = \App::get_channel(); + $channel = App::get_channel(); switch ($_SESSION['action']) { case 'import': @@ -91,7 +106,7 @@ class Webpages extends \Zotlabs\Web\Controller { } - if(\App::$is_sys && is_site_admin()) { + if(App::$is_sys && is_site_admin()) { $sys = get_sys_channel(); if($sys && intval($sys['channel_id'])) { $uid = $owner = intval($sys['channel_id']); @@ -127,8 +142,8 @@ class Webpages extends \Zotlabs\Web\Controller { // Nickname is set to the observers xchan, and profile_uid to the owner's. // This lets you post pages at other people's channels. - if((! $channel) && ($uid) && ($uid == \App::$profile_uid)) { - $channel = \App::get_channel(); + if((! $channel) && ($uid) && ($uid == App::$profile_uid)) { + $channel = App::get_channel(); } if($channel) { $channel_acl = array( @@ -144,15 +159,15 @@ class Webpages extends \Zotlabs\Web\Controller { $is_owner = ($uid && $uid == $owner); - //$o = profile_tabs($a, $is_owner, \App::$profile['channel_address']); + //$o = profile_tabs($a, $is_owner, App::$profile['channel_address']); $o = ''; $x = array( 'webpage' => ITEM_TYPE_WEBPAGE, 'is_owner' => true, - 'nickname' => \App::$profile['channel_address'], + 'nickname' => App::$profile['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, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''), + 'acl' => (($is_owner) ? populate_acl($channel_acl,false, PermissionDescription::fromGlobalPermission('view_pages')) : ''), 'permissions' => $channel_acl, 'showacl' => (($is_owner) ? true : false), 'visitor' => true, @@ -280,7 +295,7 @@ class Webpages extends \Zotlabs\Web\Controller { notice( t('Invalid file type.') . EOL); return; } - $zip = new \ZipArchive(); + $zip = new ZipArchive(); if ($zip->open($source) === true) { $tmp_folder_name = random_string(5); $website = dirname($source) . '/' . $tmp_folder_name; @@ -297,7 +312,7 @@ class Webpages extends \Zotlabs\Web\Controller { // Website files are to be imported from the channel cloud files if (($_POST) && array_key_exists('path',$_POST) && isset($_POST['cloudsubmit'])) { - $channel = \App::get_channel(); + $channel = App::get_channel(); $dirpath = get_dirpath_by_cloudpath($channel, $_POST['path']); if(!$dirpath) { notice( t('Invalid folder path.') . EOL); @@ -343,7 +358,7 @@ class Webpages extends \Zotlabs\Web\Controller { case 'importselected': require_once('include/import.php'); - $channel = \App::get_channel(); + $channel = App::get_channel(); // Import layout first so that pages that reference new layouts will find // the mid of layout items in the database @@ -438,7 +453,7 @@ class Webpages extends \Zotlabs\Web\Controller { case 'cloud': case 'zipfile': - $channel = \App::get_channel(); + $channel = App::get_channel(); $tmp_folder_name = random_string(10); $zip_folder_name = random_string(10); @@ -657,7 +672,7 @@ class Webpages extends \Zotlabs\Web\Controller { } if($action === 'zipfile') { // Generate the zip file - \Zotlabs\Lib\ExtendedZip::zipTree($tmp_folderpath, $zip_filepath, \ZipArchive::CREATE); + ExtendedZip::zipTree($tmp_folderpath, $zip_filepath, ZipArchive::CREATE); // Output the file for download header('Content-disposition: attachment; filename="' . $zip_filename . '"'); header("Content-Type: application/zip"); @@ -666,7 +681,7 @@ class Webpages extends \Zotlabs\Web\Controller { if(isset($_SESSION['exportcloudpath'])) { require_once('include/attach.php'); $cloudpath = urldecode($_SESSION['exportcloudpath']); - $channel = \App::get_channel(); + $channel = App::get_channel(); $dirpath = get_dirpath_by_cloudpath($channel, $cloudpath); if(!$dirpath) { $x = attach_mkdirp($channel, $channel['channel_hash'], array('pathname' => $cloudpath)); diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 25ecb6a6a..828af8f83 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -2,15 +2,20 @@ namespace Zotlabs\Module; -use \Zotlabs\Lib as Zlib; -use \Michelf\MarkdownExtra; +use App; +use Zotlabs\Web\Controller; +use Zotlabs\Lib\Apps; +use Zotlabs\Lib\PermissionDescription; +use Zotlabs\Lib\NativeWiki; +use Zotlabs\Lib\NativeWikiPage; +use Zotlabs\Lib\MarkdownSoap; +use Michelf\MarkdownExtra; require_once('include/acl_selectors.php'); require_once('include/conversation.php'); require_once('include/bbcode.php'); - -class Wiki extends \Zotlabs\Web\Controller { +class Wiki extends Controller { private $wiki = null; @@ -40,10 +45,14 @@ class Wiki extends \Zotlabs\Web\Controller { return login(); } - if(! feature_enabled(\App::$profile_uid,'wiki')) { - notice( t('Not found') . EOL); - return; - } + if(! Apps::system_app_installed(App::$profile_uid, 'Wiki')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'Wiki App (Not Installed):
'; + $o .= t('Provide a wiki for your channel'); + return $o; + } if(! perm_is_allowed(\App::$profile_uid,get_observer_hash(),'view_wiki')) { @@ -95,7 +104,7 @@ class Wiki extends \Zotlabs\Web\Controller { $owner['channel_deny_gid']) ? 'lock' : 'unlock' ), - 'acl' => populate_acl($owner_acl, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_wiki')), + 'acl' => populate_acl($owner_acl, false, PermissionDescription::fromGlobalPermission('view_wiki')), 'allow_cid' => acl2json($owner_acl['allow_cid']), 'allow_gid' => acl2json($owner_acl['allow_gid']), 'deny_cid' => acl2json($owner_acl['deny_cid']), @@ -117,9 +126,9 @@ class Wiki extends \Zotlabs\Web\Controller { if((argc() > 3) && (argv(2) === 'download') && (argv(3) === 'wiki')) { $resource_id = argv(4); - $w = Zlib\NativeWiki::get_wiki($owner['channel_id'],$observer_hash,$resource_id); + $w = NativeWiki::get_wiki($owner['channel_id'],$observer_hash,$resource_id); -// $w = Zlib\NativeWiki::get_wiki($owner,$observer_hash,$resource_id); +// $w = NativeWiki::get_wiki($owner,$observer_hash,$resource_id); if(! $w['htmlName']) { notice(t('Error retrieving wiki') . EOL); } @@ -157,9 +166,9 @@ class Wiki extends \Zotlabs\Web\Controller { $content = html_entity_decode($iv['body'],ENT_COMPAT,'UTF-8'); } elseif($iv['mimetype'] === 'text/markdown') { - $content = html_entity_decode(Zlib\MarkdownSoap::unescape($iv['body']),ENT_COMPAT,'UTF-8'); + $content = html_entity_decode(MarkdownSoap::unescape($iv['body']),ENT_COMPAT,'UTF-8'); } - $fname = get_iconfig($iv['id'],'nwikipage','pagetitle') . Zlib\NativeWikiPage::get_file_ext($iv); + $fname = get_iconfig($iv['id'],'nwikipage','pagetitle') . NativeWikiPage::get_file_ext($iv); $zip->addFromString($fname,$content); $pages[] = $iv['mid']; } @@ -190,7 +199,7 @@ class Wiki extends \Zotlabs\Web\Controller { switch(argc()) { case 2: - $wikis = Zlib\NativeWiki::listwikis($owner, get_observer_hash()); + $wikis = NativeWiki::listwikis($owner, get_observer_hash()); if($wikis) { $o .= replace_macros(get_markup_template('wikilist.tpl'), array( @@ -256,7 +265,7 @@ class Wiki extends \Zotlabs\Web\Controller { $pageUrlName = urldecode($page_name); $langPageUrlName = urldecode(\App::$language . '/' . $page_name); - $w = Zlib\NativeWiki::exists_by_name($owner['channel_id'], $wikiUrlName); + $w = NativeWiki::exists_by_name($owner['channel_id'], $wikiUrlName); if(! $w['resource_id']) { notice(t('Wiki not found') . EOL); @@ -268,7 +277,7 @@ class Wiki extends \Zotlabs\Web\Controller { if(! $wiki_owner) { // Check for observer permissions $observer_hash = get_observer_hash(); - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['read']) { notice(t('Permission denied.') . EOL); goaway(z_root() . '/' . argv(0) . '/' . argv(1)); @@ -289,10 +298,10 @@ class Wiki extends \Zotlabs\Web\Controller { $p = []; if(! $ignore_language) { - $p = Zlib\NativeWikiPage::get_page_content(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $langPageUrlName)); + $p = NativeWikiPage::get_page_content(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $langPageUrlName)); } if(! ($p && $p['success'])) { - $p = Zlib\NativeWikiPage::get_page_content(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); + $p = NativeWikiPage::get_page_content(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); } if(! ($p && $p['success'])) { $x = new \Zotlabs\Widget\Wiki_pages(); @@ -306,7 +315,7 @@ class Wiki extends \Zotlabs\Web\Controller { //json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true)); notice( t('Error retrieving page content') . EOL); //goaway(z_root() . '/' . argv(0) . '/' . argv(1) ); - $renderedContent = Zlib\NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName); + $renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName); $showPageControls = $wiki_editor; } else { @@ -320,15 +329,15 @@ class Wiki extends \Zotlabs\Web\Controller { // Render the Markdown-formatted page content in HTML if($mimeType == 'text/bbcode') { - $renderedContent = Zlib\NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))), argv(0) . '/' . argv(1) . '/' . $wikiUrlName); + $renderedContent = NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))), argv(0) . '/' . argv(1) . '/' . $wikiUrlName); } elseif($mimeType === 'text/plain') { $renderedContent = str_replace(["\n",' ',"\t"],[EOL,' ','    '],htmlentities($content,ENT_COMPAT,'UTF-8',false)); } elseif($mimeType === 'text/markdown') { - $content = Zlib\MarkdownSoap::unescape($content); - $html = Zlib\NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(Zlib\NativeWikiPage::bbcode($content)))); - $renderedContent = Zlib\NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName); + $content = MarkdownSoap::unescape($content); + $html = NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(NativeWikiPage::bbcode($content)))); + $renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName); } $showPageControls = $wiki_editor; } @@ -413,23 +422,23 @@ class Wiki extends \Zotlabs\Web\Controller { $content = $_POST['content']; $resource_id = $_POST['resource_id']; - $w = Zlib\NativeWiki::get_wiki($owner['channel_id'],$observer_hash,$resource_id); + $w = NativeWiki::get_wiki($owner['channel_id'],$observer_hash,$resource_id); $wikiURL = argv(0) . '/' . argv(1) . '/' . $w['urlName']; $mimeType = $_POST['mimetype']; if($mimeType === 'text/bbcode') { - $html = Zlib\NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))),$wikiURL); + $html = NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))),$wikiURL); } elseif($mimeType === 'text/markdown') { - $bb = Zlib\NativeWikiPage::bbcode($content); - $x = new ZLib\MarkdownSoap($bb); + $bb = NativeWikiPage::bbcode($content); + $x = new MarkdownSoap($bb); $md = $x->clean(); - $md = ZLib\MarkdownSoap::unescape($md); + $md = MarkdownSoap::unescape($md); $html = MarkdownExtra::defaultTransform($md); - $html = Zlib\NativeWikiPage::generate_toc(zidify_text($html)); - $html = Zlib\NativeWikiPage::convert_links($html,$wikiURL); + $html = NativeWikiPage::generate_toc(zidify_text($html)); + $html = NativeWikiPage::convert_links($html,$wikiURL); } elseif($mimeType === 'text/plain') { $html = str_replace(["\n",' ',"\t"],[EOL,' ','    '],htmlentities($content,ENT_COMPAT,'UTF-8',false)); @@ -466,7 +475,7 @@ class Wiki extends \Zotlabs\Web\Controller { return; //not reached } - $exists = Zlib\NativeWiki::exists_by_name($owner['channel_id'], $wiki['urlName']); + $exists = NativeWiki::exists_by_name($owner['channel_id'], $wiki['urlName']); if($exists['id']) { notice( t('A wiki with this name already exists.') . EOL); goaway('/wiki'); @@ -476,15 +485,15 @@ class Wiki extends \Zotlabs\Web\Controller { // Get ACL for permissions $acl = new \Zotlabs\Access\AccessList($owner); $acl->set_from_array($_POST); - $r = Zlib\NativeWiki::create_wiki($owner, $observer_hash, $wiki, $acl); + $r = NativeWiki::create_wiki($owner, $observer_hash, $wiki, $acl); if($r['success']) { - Zlib\NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']); - $homePage = Zlib\NativeWikiPage::create_page($owner['channel_id'],$observer_hash,'Home', $r['item']['resource_id'], $wiki['mimeType']); + NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']); + $homePage = NativeWikiPage::create_page($owner['channel_id'],$observer_hash,'Home', $r['item']['resource_id'], $wiki['mimeType']); if(! $homePage['success']) { notice( t('Wiki created, but error creating Home page.')); goaway(z_root() . '/wiki/' . $nick . '/' . $wiki['urlName']); } - Zlib\NativeWiki::sync_a_wiki_item($owner['channel_id'],$homePage['item_id'],$r['item']['resource_id']); + NativeWiki::sync_a_wiki_item($owner['channel_id'],$homePage['item_id'],$r['item']['resource_id']); goaway(z_root() . '/wiki/' . $nick . '/' . $wiki['urlName'] . '/' . $homePage['page']['urlName']); } else { @@ -516,7 +525,7 @@ class Wiki extends \Zotlabs\Web\Controller { return; //not reached } - $wiki = Zlib\NativeWiki::exists_by_name($owner['channel_id'], urldecode($arr['urlName'])); + $wiki = NativeWiki::exists_by_name($owner['channel_id'], urldecode($arr['urlName'])); if($wiki['resource_id']) { @@ -525,9 +534,9 @@ class Wiki extends \Zotlabs\Web\Controller { $acl = new \Zotlabs\Access\AccessList($owner); $acl->set_from_array($_POST); - $r = Zlib\NativeWiki::update_wiki($owner['channel_id'], $observer_hash, $arr, $acl); + $r = NativeWiki::update_wiki($owner['channel_id'], $observer_hash, $arr, $acl); if($r['success']) { - Zlib\NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']); + NativeWiki::sync_a_wiki_item($owner['channel_id'],$r['item_id'],$r['item']['resource_id']); goaway(z_root() . '/wiki/' . $nick); } else { @@ -549,9 +558,9 @@ class Wiki extends \Zotlabs\Web\Controller { json_return_and_die(array('message' => t('Wiki delete permission denied.'), 'success' => false)); } $resource_id = $_POST['resource_id']; - $deleted = Zlib\NativeWiki::delete_wiki($owner['channel_id'],$observer_hash,$resource_id); + $deleted = NativeWiki::delete_wiki($owner['channel_id'],$observer_hash,$resource_id); if ($deleted['success']) { - Zlib\NativeWiki::sync_a_wiki_item($owner['channel_id'],$deleted['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'],$deleted['item_id'],$resource_id); json_return_and_die(array('message' => '', 'success' => true)); } else { @@ -570,7 +579,7 @@ class Wiki extends \Zotlabs\Web\Controller { // Determine if observer has permission to create a page - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash, $mimetype); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash, $mimetype); if(! $perms['write']) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); @@ -585,10 +594,10 @@ class Wiki extends \Zotlabs\Web\Controller { json_return_and_die(array('message' => 'Error creating page. Invalid name (' . print_r($_POST,true) . ').', 'success' => false)); } - $page = Zlib\NativeWikiPage::create_page($owner['channel_id'],$observer_hash, $name, $resource_id, $mimetype); + $page = NativeWikiPage::create_page($owner['channel_id'],$observer_hash, $name, $resource_id, $mimetype); if($page['item_id']) { - $commit = Zlib\NativeWikiPage::commit(array( + $commit = NativeWikiPage::commit(array( 'commit_msg' => t('New page created'), 'resource_id' => $resource_id, 'channel_id' => $owner['channel_id'], @@ -597,7 +606,7 @@ class Wiki extends \Zotlabs\Web\Controller { )); if($commit['success']) { - Zlib\NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']), 'success' => true)); } else { @@ -616,7 +625,7 @@ class Wiki extends \Zotlabs\Web\Controller { if((argc() === 5) && (argv(2) === 'get') && (argv(3) === 'page') && (argv(4) === 'list')) { $resource_id = $_POST['resource_id']; // resource_id for wiki in db - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(!$perms['read']) { logger('Wiki read permission denied.' . EOL); json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false)); @@ -648,16 +657,16 @@ class Wiki extends \Zotlabs\Web\Controller { } // Determine if observer has permission to save content - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); } - $saved = Zlib\NativeWikiPage::save_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'content' => $content)); + $saved = NativeWikiPage::save_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'content' => $content)); if($saved['success']) { - $commit = Zlib\NativeWikiPage::commit(array( + $commit = NativeWikiPage::commit(array( 'commit_msg' => $commitMsg, 'pageUrlName' => $pageUrlName, 'resource_id' => $resource_id, @@ -667,7 +676,7 @@ class Wiki extends \Zotlabs\Web\Controller { )); if($commit['success']) { - Zlib\NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true)); } else { @@ -688,7 +697,7 @@ class Wiki extends \Zotlabs\Web\Controller { // Determine if observer has permission to read content - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['read']) { logger('Wiki read permission denied.' . EOL); json_return_and_die(array('historyHTML' => '', 'message' => 'Permission denied.', 'success' => false)); @@ -720,15 +729,15 @@ class Wiki extends \Zotlabs\Web\Controller { json_return_and_die(array('success' => false)); } - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); } - $deleted = Zlib\NativeWikiPage::delete_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); + $deleted = NativeWikiPage::delete_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); if($deleted['success']) { - Zlib\NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true)); } else { @@ -744,13 +753,13 @@ class Wiki extends \Zotlabs\Web\Controller { $commitHash = $_POST['commitHash']; // Determine if observer has permission to revert pages - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied.' . EOL); json_return_and_die(array('success' => false)); } - $reverted = Zlib\NativeWikiPage::revert_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'commitHash' => $commitHash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); + $reverted = NativeWikiPage::revert_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'commitHash' => $commitHash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); if($reverted['success']) { json_return_and_die(array('content' => $reverted['content'], 'message' => '', 'success' => true)); } else { @@ -766,13 +775,13 @@ class Wiki extends \Zotlabs\Web\Controller { $currentCommit = $_POST['currentCommit']; // Determine if observer has permission to revert pages - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(!$perms['read']) { logger('Wiki read permission denied.' . EOL); json_return_and_die(array('success' => false)); } - $compare = Zlib\NativeWikiPage::compare_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'currentCommit' => $currentCommit, 'compareCommit' => $compareCommit, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); + $compare = NativeWikiPage::compare_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'currentCommit' => $currentCommit, 'compareCommit' => $compareCommit, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName)); if($compare['success']) { $diffHTML = '
' . t('Current Revision') . '' . t('Selected Revision') . '
' . $compare['diff']; json_return_and_die(array('diff' => $diffHTML, 'message' => '', 'success' => true)); @@ -794,16 +803,16 @@ class Wiki extends \Zotlabs\Web\Controller { } // Determine if observer has permission to rename pages - $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); + $perms = NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); if(! $perms['write']) { logger('Wiki write permission denied. ' . EOL); json_return_and_die(array('success' => false)); } - $renamed = Zlib\NativeWikiPage::rename_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'pageNewName' => $pageNewName)); + $renamed = NativeWikiPage::rename_page(array('channel_id' => $owner['channel_id'], 'observer_hash' => $observer_hash, 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'pageNewName' => $pageNewName)); if($renamed['success']) { - $commit = Zlib\NativeWikiPage::commit(array( + $commit = NativeWikiPage::commit(array( 'channel_id' => $owner['channel_id'], 'commit_msg' => 'Renamed ' . urldecode($pageUrlName) . ' to ' . $renamed['page']['htmlName'], 'resource_id' => $resource_id, @@ -811,7 +820,7 @@ class Wiki extends \Zotlabs\Web\Controller { 'pageUrlName' => $pageNewName )); if($commit['success']) { - Zlib\NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); + NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); json_return_and_die(array('name' => $renamed['page'], 'message' => 'Wiki git repo commit made', 'success' => true)); } else { diff --git a/Zotlabs/Widget/Appstore.php b/Zotlabs/Widget/Appstore.php index 237707733..6a00ac06a 100644 --- a/Zotlabs/Widget/Appstore.php +++ b/Zotlabs/Widget/Appstore.php @@ -10,9 +10,9 @@ class Appstore { return replace_macros(get_markup_template('appstore.tpl'), [ '$title' => t('App Collections'), '$options' => [ - [ z_root() . '/apps/available', t('Available Apps'), $store ], - [ z_root() . '/apps', t('Installed apps'), 1 - $store ] + [ z_root() . '/apps', t('Installed apps'), 1 - $store ], + [ z_root() . '/apps/available', t('Available Apps'), $store ] ] ]); } -} \ No newline at end of file +} -- cgit v1.2.3 From a1d5ce3716d09b7ccd81e252309ca9fd5e841b26 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 13 Sep 2018 10:59:37 +0200 Subject: remove profile_tabs() which has been deprecated and replaced by channel_apps() --- Zotlabs/Module/Bookmarks.php | 1 - Zotlabs/Module/Cal.php | 6 +----- Zotlabs/Module/Chat.php | 1 - Zotlabs/Module/Photos.php | 3 --- Zotlabs/Module/Sharedwithme.php | 1 - Zotlabs/Module/Webpages.php | 2 +- Zotlabs/Module/Wiki.php | 2 +- 7 files changed, 3 insertions(+), 13 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php index e147ffe6c..cea0d9759 100644 --- a/Zotlabs/Module/Bookmarks.php +++ b/Zotlabs/Module/Bookmarks.php @@ -71,7 +71,6 @@ class Bookmarks extends \Zotlabs\Web\Controller { $channel = \App::get_channel(); - //$o = profile_tabs($a,true,$channel['channel_address']); $o = ''; $o .= '
'; diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index c8403e979..87c13ef4e 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -88,9 +88,6 @@ class Cal extends \Zotlabs\Web\Controller { $o = ''; - //$tabs = profile_tabs($a, True, $channel['channel_address']); - $tabs = ''; - $mode = 'view'; $y = 0; $m = 0; @@ -347,8 +344,7 @@ class Cal extends \Zotlabs\Web\Controller { '$next' => t('Next'), '$today' => t('Today'), '$form' => $form, - '$expandform' => ((x($_GET,'expandform')) ? true : false), - '$tabs' => $tabs + '$expandform' => ((x($_GET,'expandform')) ? true : false) )); if (x($_GET,'id')){ echo $o; killme(); } diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index 378c9f4dd..71138e8d8 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -212,7 +212,6 @@ class Chat extends \Zotlabs\Web\Controller { require_once('include/conversation.php'); - //$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']); $o = ''; if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) { diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 489bffc4a..f97f31ff7 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -620,10 +620,7 @@ class Photos extends \Zotlabs\Web\Controller { $o .= "\r\n"; - // tabs - $_is_owner = (local_channel() && (local_channel() == $owner_uid)); - //$o .= profile_tabs($a,$_is_owner, \App::$data['channel']['channel_address']); /** * Display upload form diff --git a/Zotlabs/Module/Sharedwithme.php b/Zotlabs/Module/Sharedwithme.php index 2c97e9726..c986f6695 100644 --- a/Zotlabs/Module/Sharedwithme.php +++ b/Zotlabs/Module/Sharedwithme.php @@ -97,7 +97,6 @@ class Sharedwithme extends \Zotlabs\Web\Controller { } - //$o = profile_tabs($a, $is_owner, $channel['channel_address']); $o = ''; $o .= replace_macros(get_markup_template('sharedwithme.tpl'), array( diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index 991c5ee71..c6599db3b 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -159,7 +159,7 @@ class Webpages extends Controller { $is_owner = ($uid && $uid == $owner); - //$o = profile_tabs($a, $is_owner, App::$profile['channel_address']); + $o = ''; $x = array( diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 828af8f83..0fb5a4605 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -118,7 +118,7 @@ class Wiki extends Controller { } $is_owner = ((local_channel()) && (local_channel() == \App::$profile['profile_uid']) ? true : false); - //$o = profile_tabs($a, $is_owner, \App::$profile['channel_address']); + $o = ''; // Download a wiki -- cgit v1.2.3 From 56f88f2e30ef75fa7e41cbcbbc6344abc6b7d37d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 13 Sep 2018 11:32:43 +0200 Subject: move chat from feature to apps --- Zotlabs/Lib/Apps.php | 2 +- Zotlabs/Module/Apps.php | 4 +-- Zotlabs/Module/Chat.php | 69 ++++++++++++++++++++++++++++--------------------- 3 files changed, 42 insertions(+), 33 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 860a799ef..6b87ac6cb 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -303,7 +303,7 @@ class Apps { 'Admin' => t('Site Admin'), 'Report Bug' => t('Report Bug'), 'View Bookmarks' => t('View Bookmarks'), - 'My Chatrooms' => t('My Chatrooms'), + 'Chatrooms' => t('Chatrooms'), 'Connections' => t('Connections'), 'Remote Diagnostics' => t('Remote Diagnostics'), 'Suggest Channels' => t('Suggest Channels'), diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php index 11025ce6e..05b4495fc 100644 --- a/Zotlabs/Module/Apps.php +++ b/Zotlabs/Module/Apps.php @@ -50,8 +50,8 @@ class Apps extends \Zotlabs\Web\Controller { '$title' => (($available) ? t('Available Apps') : t('Installed Apps')), '$apps' => $apps, '$authed' => ((local_channel()) ? true : false), - '$manage' => (($available) ? '' : t('Manage apps')), - '$create' => (($mode == 'edit') ? t('Create new app') : '') + '$manage' => (($available) ? '' : t('Manage Apps')), + '$create' => (($mode == 'edit') ? t('Create Custom App') : '') )); } diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index 71138e8d8..551dc5e2a 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -1,13 +1,19 @@ 2) && (argv(2) === 'view')) { $which = $channel['channel_address']; @@ -49,16 +55,16 @@ class Chat extends \Zotlabs\Web\Controller { if((! $room) || (! local_channel())) return; - $channel = \App::get_channel(); + $channel = App::get_channel(); if($_POST['action'] === 'drop') { logger('delete chatroom'); - Zlib\Chatroom::destroy($channel,array('cr_name' => $room)); + Chatroom::destroy($channel,array('cr_name' => $room)); goaway(z_root() . '/chat/' . $channel['channel_address']); } - $acl = new \Zotlabs\Access\AccessList($channel); + $acl = new AccessList($channel); $acl->set_from_array($_REQUEST); $arr = $acl->get(); @@ -67,7 +73,7 @@ class Chat extends \Zotlabs\Web\Controller { if(intval($arr['expire']) < 0) $arr['expire'] = 0; - Zlib\Chatroom::create($channel,$arr); + Chatroom::create($channel,$arr); $x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1", dbesc($room), @@ -88,26 +94,35 @@ class Chat extends \Zotlabs\Web\Controller { function get() { + + if(! Apps::system_app_installed(App::$profile_uid, 'Chatrooms')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'Chatrooms App (Not Installed):
'; + $o .= t('Access Controlled Chatrooms'); + return $o; + } if(local_channel()) { - $channel = \App::get_channel(); - nav_set_selected('My Chatrooms'); + $channel = App::get_channel(); + nav_set_selected('Chatrooms'); } - $ob = \App::get_observer(); + $ob = App::get_observer(); $observer = get_observer_hash(); if(! $observer) { notice( t('Permission denied.') . EOL); return; } - if(! perm_is_allowed(\App::$profile['profile_uid'],$observer,'chat')) { + if(! perm_is_allowed(App::$profile['profile_uid'],$observer,'chat')) { notice( t('Permission denied.') . EOL); return; } if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) { - Zlib\Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']); + Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']); goaway(z_root() . '/channel/' . argv(1)); } @@ -160,16 +175,16 @@ class Chat extends \Zotlabs\Web\Controller { $room_id = intval(argv(2)); $bookmark_link = get_bookmark_link($ob); - $x = Zlib\Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']); + $x = Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']); if(! $x) return; $x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1", intval($room_id), - intval(\App::$profile['profile_uid']) + intval(App::$profile['profile_uid']) ); if($x) { - $acl = new \Zotlabs\Access\AccessList(false); + $acl = new AccessList(false); $acl->set($x[0]); $private = $acl->is_private(); @@ -208,18 +223,12 @@ class Chat extends \Zotlabs\Web\Controller { )); return $o; } - - + require_once('include/conversation.php'); $o = ''; - - if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) { - notice( t('Feature disabled.') . EOL); - return $o; - } - $acl = new \Zotlabs\Access\AccessList($channel); + $acl = new AccessList($channel); $channel_acl = $acl->get(); $lockstate = (($channel_acl['allow_cid'] || $channel_acl['allow_gid'] || $channel_acl['deny_cid'] || $channel_acl['deny_gid']) ? 'lock' : 'unlock'); @@ -243,17 +252,17 @@ class Chat extends \Zotlabs\Web\Controller { )); } - $rooms = Zlib\Chatroom::roomlist(\App::$profile['profile_uid']); + $rooms = Chatroom::roomlist(App::$profile['profile_uid']); $o .= replace_macros(get_markup_template('chatrooms.tpl'), array( - '$header' => sprintf( t('%1$s\'s Chatrooms'), \App::$profile['fullname']), + '$header' => sprintf( t('%1$s\'s Chatrooms'), App::$profile['fullname']), '$name' => t('Name'), '$baseurl' => z_root(), - '$nickname' => \App::$profile['channel_address'], + '$nickname' => App::$profile['channel_address'], '$rooms' => $rooms, '$norooms' => t('No chatrooms available'), '$newroom' => t('Create New'), - '$is_owner' => ((local_channel() && local_channel() == \App::$profile['profile_uid']) ? 1 : 0), + '$is_owner' => ((local_channel() && local_channel() == App::$profile['profile_uid']) ? 1 : 0), '$chatroom_new' => $chatroom_new, '$expire' => t('Expiration'), '$expire_unit' => t('min') //minutes -- cgit v1.2.3 From 869534fafa543a76e58c32d5aa8f674217682162 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 13 Sep 2018 11:53:59 +0200 Subject: remove network_tabs() which has been deprecated and replaced by activity_{order, filters} widgets --- Zotlabs/Module/Network.php | 12 ++++-------- Zotlabs/Widget/Activity_filter.php | 2 +- Zotlabs/Widget/Activity_order.php | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index c3db15ef2..ffe605538 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -167,8 +167,6 @@ class Network extends \Zotlabs\Web\Controller { } if(! $update) { - $tabs = ''; //network_tabs(); - $o .= $tabs; // search terms header if($search) { @@ -256,8 +254,7 @@ class Network extends \Zotlabs\Web\Controller { )); } - $o = $tabs; - $o .= $title; + $o = $title; $o .= $status_editor; } @@ -283,8 +280,7 @@ class Network extends \Zotlabs\Web\Controller { '$title' => '' . urlencode($cid_r[0]['xchan_name']) . ' ' . $cid_r[0]['xchan_name'] . '' )); - $o = $tabs; - $o .= $title; + $o = $title; $o .= $status_editor; } elseif($xchan) { @@ -297,8 +293,8 @@ class Network extends \Zotlabs\Web\Controller { $title = replace_macros(get_markup_template("section_title.tpl"),array( '$title' => '' . urlencode($r[0]['xchan_name']) . ' ' . $r[0]['xchan_name'] . '' )); - $o = $tabs; - $o .= $title; + + $o = $title; $o .= $status_editor; } diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php index fadf39144..d725f8b55 100644 --- a/Zotlabs/Widget/Activity_filter.php +++ b/Zotlabs/Widget/Activity_filter.php @@ -180,7 +180,7 @@ class Activity_filter { $arr = ['tabs' => $tabs]; - call_hooks('network_tabs', $arr); + call_hooks('activity_filter', $arr); $o = ''; diff --git a/Zotlabs/Widget/Activity_order.php b/Zotlabs/Widget/Activity_order.php index 27d1a971a..2dceee70e 100644 --- a/Zotlabs/Widget/Activity_order.php +++ b/Zotlabs/Widget/Activity_order.php @@ -110,7 +110,7 @@ class Activity_order { $arr = ['tabs' => $tabs]; - call_hooks('network_tabs', $arr); + call_hooks('activity_order', $arr); $o = ''; -- cgit v1.2.3 From 7856f5882bceaf83d5df42e117c23badc89ad1a8 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 15 Sep 2018 10:10:43 +0200 Subject: appify cdav stuff. WARNING: if you use caldav or carddav from a client or the webinterface you will need to enable those apps to make things work again --- Zotlabs/Module/Cdav.php | 52 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index 6737ac4ee..69030b582 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -1,6 +1,9 @@ setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . 'CalDAV/CardDAV'); if (local_channel()) { + logger('loggedin'); - $channel = \App::get_channel(); + + if((argv(1) == 'calendars') && (!Apps::system_app_installed(local_channel(), 'CalDAV'))) { + killme(); + } + + if((argv(1) == 'addressbooks') && (!Apps::system_app_installed(local_channel(), 'CardDAV'))) { + killme(); + } + + $channel = App::get_channel(); $auth->setCurrentUser($channel['channel_address']); $auth->channel_id = $channel['channel_id']; $auth->channel_hash = $channel['channel_hash']; @@ -161,12 +174,15 @@ class Cdav extends \Zotlabs\Web\Controller { $nodes = [ // /principals new \Sabre\CalDAV\Principal\Collection($principalBackend), + // /calendars new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend), + // /addressbook - new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend), + new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend) ]; + // The object tree needs in turn to be passed to the server class $server = new \Sabre\DAV\Server($nodes); @@ -204,7 +220,15 @@ class Cdav extends \Zotlabs\Web\Controller { if(! local_channel()) return; - $channel = \App::get_channel(); + if((argv(1) === 'calendar') && (! Apps::system_app_installed(local_channel(), 'CalDAV'))) { + return; + } + + if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) { + return; + } + + $channel = App::get_channel(); $principalUri = 'principals/' . $channel['channel_address']; if(!cdav_principal($principalUri)) @@ -807,7 +831,25 @@ class Cdav extends \Zotlabs\Web\Controller { if(!local_channel()) return; - $channel = \App::get_channel(); + if((argv(1) === 'calendar') && (! Apps::system_app_installed(local_channel(), 'CalDAV'))) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'CalDAV App (Not Installed):
'; + $o .= t('CalDAV capable calendar'); + return $o; + } + + if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'CardDAV App (Not Installed):
'; + $o .= t('CalDAV capable addressbook'); + return $o; + } + + $channel = App::get_channel(); $principalUri = 'principals/' . $channel['channel_address']; $pdo = \DBA::$dba->db; @@ -874,7 +916,7 @@ class Cdav extends \Zotlabs\Web\Controller { $o .= replace_macros(get_markup_template('cdav_calendar.tpl'), [ '$sources' => $sources, '$color' => $color, - '$lang' => \App::$language, + '$lang' => App::$language, '$first_day' => $first_day, '$prev' => t('Previous'), '$next' => t('Next'), -- cgit v1.2.3 From 0f9a8a43e4ab274e251240f6091a5bf87c2ac205 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 15 Sep 2018 10:48:51 +0200 Subject: appify invite --- Zotlabs/Module/Cdav.php | 3 ++- Zotlabs/Module/Invite.php | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index 69030b582..bff308dfa 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -3,13 +3,14 @@ namespace Zotlabs\Module; use App; use Zotlabs\Lib\Apps; +use Zotlabs\Web\Controller; require_once('include/event.php'); require_once('include/auth.php'); require_once('include/security.php'); -class Cdav extends \Zotlabs\Web\Controller { +class Cdav extends Controller { function init() { diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php index 359f99b3e..0a79387ce 100644 --- a/Zotlabs/Module/Invite.php +++ b/Zotlabs/Module/Invite.php @@ -1,6 +1,10 @@ Invite App (Not Installed):
'; + $o .= t('Send email invitations to join this network'); + return $o; + } + nav_set_selected('Invite'); $tpl = get_markup_template('invite.tpl'); @@ -127,11 +140,11 @@ class Invite extends \Zotlabs\Web\Controller { } } - $ob = \App::get_observer(); + $ob = App::get_observer(); if(! $ob) return $o; - $channel = \App::get_channel(); + $channel = App::get_channel(); $o = replace_macros($tpl, array( '$form_security_token' => get_form_security_token("send_invite"), -- cgit v1.2.3 From 299eb469f8d4d674c49e41162d28f237c0d7294f Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 15 Sep 2018 11:00:41 +0200 Subject: appify mood --- Zotlabs/Module/Invite.php | 4 ++++ Zotlabs/Module/Mood.php | 23 ++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php index 0a79387ce..234802746 100644 --- a/Zotlabs/Module/Invite.php +++ b/Zotlabs/Module/Invite.php @@ -21,6 +21,10 @@ class Invite extends Controller { notice( t('Permission denied.') . EOL); return; } + + if(! Apps::system_app_installed(local_channel(), 'Invite')) { + return; + } check_form_security_token_redirectOnErr('/', 'send_invite'); diff --git a/Zotlabs/Module/Mood.php b/Zotlabs/Module/Mood.php index ad29ec7e8..cceef5ffa 100644 --- a/Zotlabs/Module/Mood.php +++ b/Zotlabs/Module/Mood.php @@ -1,21 +1,29 @@ Mood App (Not Installed):
'; + $o .= t('Set your current mood and tell your friends'); + return $o; + } + nav_set_selected('Mood'); $parent = ((x($_GET,'parent')) ? intval($_GET['parent']) : '0'); -- cgit v1.2.3 From 791ff25d52c7f7e95758f1218a1621012b15be7c Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 15 Sep 2018 11:09:16 +0200 Subject: appify poke --- Zotlabs/Module/Poke.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Poke.php b/Zotlabs/Module/Poke.php index d13ec5ced..46dcf6dd3 100644 --- a/Zotlabs/Module/Poke.php +++ b/Zotlabs/Module/Poke.php @@ -1,6 +1,10 @@ Poke App (Not Installed):
'; + $o .= t('Poke somebody in your addressbook'); + return $o; + } + nav_set_selected('Poke'); $name = ''; -- cgit v1.2.3 From 07cd1d1272bd301c2f41f5579697754ccbbf5ae3 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sun, 16 Sep 2018 09:30:07 +0200 Subject: appification of the lang module --- Zotlabs/Module/Lang.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Lang.php b/Zotlabs/Module/Lang.php index 0e5d85d05..9858beecd 100644 --- a/Zotlabs/Module/Lang.php +++ b/Zotlabs/Module/Lang.php @@ -1,13 +1,28 @@ Language App (Not Installed):
'; + $o .= t('Change UI language'); + return $o; + } + } + nav_set_selected('Language'); return lang_selector(); + } - } -- cgit v1.2.3 From 593a5072d9b738ea036167f15776f90e829a1e64 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 16 Sep 2018 20:00:20 -0700 Subject: Some improvements to setup checks: image library and pdo support --- Zotlabs/Module/Setup.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index a3832d156..50b40834b 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -526,14 +526,21 @@ class Setup extends \Zotlabs\Web\Controller { $ck_funcs[0]['status'] = false; $ck_funcs[0]['help'] = t('Error: libCURL PHP module required but not installed.'); } - if(! function_exists('imagecreatefromjpeg')) { + if((! function_exists('imagecreatefromjpeg')) || (! class_exists('Imagick'))) { $ck_funcs[1]['status'] = false; - $ck_funcs[1]['help'] = t('Error: GD graphics PHP module with JPEG support required but not installed.'); + $ck_funcs[1]['help'] = t('Error: GD PHP module with JPEG support or ImageMagick graphics library required but not installed.'); } if(! function_exists('openssl_public_encrypt')) { $ck_funcs[2]['status'] = false; $ck_funcs[2]['help'] = t('Error: openssl PHP module required but not installed.'); } + if(class_exists('PDO')) { + $x = PDO::getAvailableDrivers(); + if((! in_array('mysql',$x)) && (! in_array('pgsql',$x))) { + $ck_funcs[3]['status'] = false; + $ck_funcs[3]['help'] = t('Error: PDO database PHP module missing a driver for either mysql or pgsql.'); + } + } if(! class_exists('PDO')) { $ck_funcs[3]['status'] = false; $ck_funcs[3]['help'] = t('Error: PDO database PHP module required but not installed.'); -- cgit v1.2.3 From a0cf2b53e03098f459edec6ac395df9750efe333 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Sun, 16 Sep 2018 23:01:17 -0400 Subject: Add hook to allow addons to filter the list returned by app_list --- Zotlabs/Lib/Apps.php | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 6b87ac6cb..aa7e2282d 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -722,6 +722,9 @@ class Apps { ); if($r) { + $hookinfo = Array('uid'=>$uid,'deleted'=>$deleted,'cats'=>$cats,'apps'=>$r); + call_hooks('app_list',$hookinfo); + $r = $hookinfo['apps']; for($x = 0; $x < count($r); $x ++) { if(! $r[$x]['app_system']) $r[$x]['type'] = 'personal'; -- cgit v1.2.3 From 2f6cb764a4670f848123153e44d6aa58d6ab01b7 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 17 Sep 2018 10:30:47 +0200 Subject: prepare submodule to interact with route --- Zotlabs/Module/Articles.php | 2 +- Zotlabs/Web/SubModule.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index d622b221a..7af1ab6b8 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -45,7 +45,7 @@ class Articles extends Controller { return $o; } - nav_set_selected(t('Articles')); + nav_set_selected('Articles'); head_add_link([ 'rel' => 'alternate', diff --git a/Zotlabs/Web/SubModule.php b/Zotlabs/Web/SubModule.php index 7c8404201..763a55d86 100644 --- a/Zotlabs/Web/SubModule.php +++ b/Zotlabs/Web/SubModule.php @@ -2,6 +2,8 @@ namespace Zotlabs\Web; +use Zotlabs\Extend\Route; + /* * @brief * @@ -31,9 +33,23 @@ class SubModule { $filename = 'Zotlabs/Module/' . ucfirst(argv(0)) . '/'. ucfirst(argv($whicharg)) . '.php'; $modname = '\\Zotlabs\\Module\\' . ucfirst(argv(0)) . '\\' . ucfirst(argv($whicharg)); + if(file_exists($filename)) { $this->controller = new $modname(); } + + $routes = Route::get(); + + if($routes) { + foreach($routes as $route) { + if(is_array($route) && strtolower($route[1]) === strtolower(argv(0)) . '/' . strtolower(argv($whicharg))) { + include_once($route[0]); + if(class_exists($modname)) { + $this->controller = new $modname; + } + } + } + } } /** @@ -43,6 +59,7 @@ class SubModule { * @return boolean|mixed */ function call($method) { + if(! $this->controller) return false; -- cgit v1.2.3 From a9853e6033ed6a9af639606fa73bb5b40d2fbbcb Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 17 Sep 2018 11:36:11 +0200 Subject: seperate settings for mod network --- Zotlabs/Module/Settings/Network.php | 128 ++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 Zotlabs/Module/Settings/Network.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php new file mode 100644 index 000000000..14a118f2c --- /dev/null +++ b/Zotlabs/Module/Settings/Network.php @@ -0,0 +1,128 @@ + 'settings/network', + '$form_security_token' => get_form_security_token("settings_network"), + '$title' => t('Activity Settings'), + '$features' => $arr, + '$baseurl' => z_root(), + '$submit' => t('Submit'), + )); + + return $o; + } + + function get_features() { + $arr = [ + + [ + 'archives', + t('Search by Date'), + t('Ability to select posts by date ranges'), + false, + get_config('feature_lock','archives') + ], + + [ + 'savedsearch', + t('Saved Searches'), + t('Save search terms for re-use'), + false, + get_config('feature_lock','savedsearch') + ], + + [ + 'order_tab', + t('Alternate Stream Order'), + t('Ability to order the stream by last post date, last comment date or unthreaded activities'), + false, + get_config('feature_lock','order_tab') + ], + + [ + 'name_tab', + t('Contact Filter'), + t('Ability to display only posts of a selected contact'), + false, + get_config('feature_lock','name_tab') + ], + + [ + 'forums_tab', + t('Forum Filter'), + t('Ability to display only posts of a specific forum'), + false, + get_config('feature_lock','forums_tab') + ], + + [ + 'personal_tab', + t('Personal Posts Filter'), + t('Ability to display only posts that you\'ve interacted on'), + false, + get_config('feature_lock','personal_tab') + ], + + [ + 'affinity', + t('Affinity Tool'), + t('Filter stream activity by depth of relationships'), + false, + get_config('feature_lock','affinity') + ], + + [ + 'suggest', + t('Suggest Channels'), + t('Show friend and connection suggestions'), + false, + get_config('feature_lock','suggest') + ], + + [ + 'connfilter', + t('Connection Filtering'), + t('Filter incoming posts from connections based on keywords/content'), + false, + get_config('feature_lock','connfilter') + ] + + ]; + + return $arr; + + } + +} -- cgit v1.2.3 From fdc89d1b8972c2bad896eb3d42086b0e91e3c01b Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 17 Sep 2018 13:03:17 -0700 Subject: pdo install check requires namespacing --- Zotlabs/Module/Setup.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index 50b40834b..693f3309e 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -526,7 +526,7 @@ class Setup extends \Zotlabs\Web\Controller { $ck_funcs[0]['status'] = false; $ck_funcs[0]['help'] = t('Error: libCURL PHP module required but not installed.'); } - if((! function_exists('imagecreatefromjpeg')) || (! class_exists('Imagick'))) { + if((! function_exists('imagecreatefromjpeg')) || (! class_exists('\\Imagick'))) { $ck_funcs[1]['status'] = false; $ck_funcs[1]['help'] = t('Error: GD PHP module with JPEG support or ImageMagick graphics library required but not installed.'); } @@ -534,14 +534,14 @@ class Setup extends \Zotlabs\Web\Controller { $ck_funcs[2]['status'] = false; $ck_funcs[2]['help'] = t('Error: openssl PHP module required but not installed.'); } - if(class_exists('PDO')) { - $x = PDO::getAvailableDrivers(); + if(class_exists('\\PDO')) { + $x = \PDO::getAvailableDrivers(); if((! in_array('mysql',$x)) && (! in_array('pgsql',$x))) { $ck_funcs[3]['status'] = false; $ck_funcs[3]['help'] = t('Error: PDO database PHP module missing a driver for either mysql or pgsql.'); } } - if(! class_exists('PDO')) { + if(! class_exists('\\PDO')) { $ck_funcs[3]['status'] = false; $ck_funcs[3]['help'] = t('Error: PDO database PHP module required but not installed.'); } -- cgit v1.2.3 From a1f3a5d9b680157b8a9f0bf61852a76530ee11f3 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 17 Sep 2018 22:16:10 +0200 Subject: remove unused variable --- Zotlabs/Module/Settings/Network.php | 1 - 1 file changed, 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index 14a118f2c..7d19d7c51 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -37,7 +37,6 @@ class Network { '$form_security_token' => get_form_security_token("settings_network"), '$title' => t('Activity Settings'), '$features' => $arr, - '$baseurl' => z_root(), '$submit' => t('Submit'), )); -- cgit v1.2.3 From 71c599f50ef2933f3898d55823aec351f95d5828 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 17 Sep 2018 22:16:42 +0200 Subject: remove superfluous comma --- Zotlabs/Module/Settings/Network.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index 7d19d7c51..4e2e3915e 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -37,7 +37,7 @@ class Network { '$form_security_token' => get_form_security_token("settings_network"), '$title' => t('Activity Settings'), '$features' => $arr, - '$submit' => t('Submit'), + '$submit' => t('Submit') )); return $o; -- cgit v1.2.3 From cc5ef57843f4012f7319a0ffd687fe26950a7790 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Mon, 17 Sep 2018 18:40:49 -0700 Subject: fix listeners table create and expire federation had a syntax error --- Zotlabs/Daemon/Cron.php | 2 +- Zotlabs/Update/_1220.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php index d1c516f96..25e49b817 100644 --- a/Zotlabs/Daemon/Cron.php +++ b/Zotlabs/Daemon/Cron.php @@ -60,7 +60,7 @@ class Cron { drop_item($rr['id'],false,(($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL)); if($rr['item_wall']) { // The notifier isn't normally invoked unless item_drop is interactive. - Zotlabs\Daemon\Master::Summon( [ 'Notifier', 'drop', $rr['id'] ] ); + Master::Summon( [ 'Notifier', 'drop', $rr['id'] ] ); } } } diff --git a/Zotlabs/Update/_1220.php b/Zotlabs/Update/_1220.php index adcb8c9c6..6ce09c16b 100644 --- a/Zotlabs/Update/_1220.php +++ b/Zotlabs/Update/_1220.php @@ -26,14 +26,14 @@ class _1220 { if(ACTIVE_DBTYPE == DBTYPE_MYSQL) { $r = q("CREATE TABLE IF NOT EXISTS listeners ( id int(11) NOT NULL AUTO_INCREMENT, - target_id varchar(191) CHARACTER SET utf8mb4 NOT NULL DEFAULT '', - portable_id varchar(191) CHARACTER SET utf8mb4 NOT NULL DEFAULT '', - ltype int(11) NOT NULL DEFAULT '0', + target_id varchar(191) NOT NULL DEFAULT '', + portable_id varchar(191) NOT NULL DEFAULT '', + ltype int(11) NOT NULL DEFAULT 0, PRIMARY KEY (id), KEY target_id (target_id), KEY portable_id (portable_id), KEY ltype (ltype) -) ENGINE=InnoDB DEFAULT CHARSET=utf8"); +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); } -- cgit v1.2.3 From 34fec995f711b03bc19580ee9e57c22712cf51df Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 19 Sep 2018 15:00:06 +0200 Subject: allow a second url in apd files for settings, hide pin and star buttons in edit mode and use strpos() instead of strstr() in some places --- Zotlabs/Lib/Apps.php | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index aa7e2282d..905a20ee0 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -388,9 +388,7 @@ class Apps { // This will catch somebody clicking on a system "available" app that hasn't had the path macros replaced // and they are allowed to see the app - - - if(strstr($papp['url'],'$baseurl') || strstr($papp['url'],'$nick') || strstr($papp['photo'],'$baseurl') || strstr($pap['photo'],'$nick')) { + if(strpos($papp['url'],'$baseurl') || strpos($papp['url'],'$nick') || strpos($papp['photo'],'$baseurl') || strpos($papp['photo'],'$nick')) { $view_channel = local_channel(); if(! $view_channel) { $sys = get_sys_channel(); @@ -399,7 +397,13 @@ class Apps { self::app_macros($view_channel,$papp); } - if(! strstr($papp['url'],'://')) + if(strpos($papp['url'], ',')) { + $urls = explode(',', $papp['url']); + $papp['url'] = trim($urls[0]); + $papp['settings_url'] = trim($urls[1]); + } + + if(! strpos($papp['url'],'://')) $papp['url'] = z_root() . ((strpos($papp['url'],'/') === 0) ? '' : '/') . $papp['url']; @@ -468,7 +472,9 @@ class Apps { $hosturl = ''; if(local_channel()) { - $installed = self::app_installed(local_channel(),$papp); + if(self::app_installed(local_channel(),$papp) && !$papp['deleted']) + $installed = true; + $hosturl = z_root() . '/'; } elseif(remote_channel()) { @@ -495,6 +501,7 @@ class Apps { if($mode === 'install') { $papp['embed'] = true; } + return replace_macros(get_markup_template('app.tpl'),array( '$app' => $papp, '$icon' => $icon, @@ -503,11 +510,12 @@ class Apps { '$installed' => $installed, '$action_label' => (($hosturl && in_array($mode, ['view','install'])) ? $install_action : ''), '$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''), - '$delete' => ((local_channel() && $installed && $mode == 'edit') ? t('Delete') : ''), - '$undelete' => ((local_channel() && $installed && $mode == 'edit') ? t('Undelete') : ''), + '$delete' => ((local_channel() && $mode == 'edit') ? t('Delete') : ''), + '$undelete' => ((local_channel() && $mode == 'edit') ? t('Undelete') : ''), + '$settings_url' => ((local_channel() && $installed && $mode == 'list') ? $papp['settings_url'] : ''), '$deleted' => $papp['deleted'], - '$feature' => (($papp['embed']) ? false : true), - '$pin' => (($papp['embed']) ? false : true), + '$feature' => (($papp['embed'] || $mode == 'edit') ? false : true), + '$pin' => (($papp['embed'] || $mode == 'edit') ? false : true), '$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true), '$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true), '$navapps' => (($mode == 'nav') ? true : false), @@ -912,7 +920,7 @@ class Apps { $arr['author'] = $sys['channel_hash']; } - if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (! strstr($arr['photo'],z_root()))) { + if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (! strpos($arr['photo'],z_root()))) { $x = import_xchan_photo(str_replace('$baseurl',z_root(),$arr['photo']),get_observer_hash(),true); $arr['photo'] = $x[1]; } @@ -998,7 +1006,7 @@ class Apps { if((! $darray['app_url']) || (! $darray['app_id'])) return $ret; - if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (! strstr($arr['photo'],z_root()))) { + if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (! strpos($arr['photo'],z_root()))) { $x = import_xchan_photo(str_replace('$baseurl',z_root(),$arr['photo']),get_observer_hash(),true); $arr['photo'] = $x[1]; } -- cgit v1.2.3 From 2c1560e027bc3dc6c1d611ff782b29eeabdb76f0 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 19 Sep 2018 17:56:23 -0700 Subject: fix setup --- Zotlabs/Module/Setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index 693f3309e..c0716ca7c 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -526,7 +526,7 @@ class Setup extends \Zotlabs\Web\Controller { $ck_funcs[0]['status'] = false; $ck_funcs[0]['help'] = t('Error: libCURL PHP module required but not installed.'); } - if((! function_exists('imagecreatefromjpeg')) || (! class_exists('\\Imagick'))) { + if((! function_exists('imagecreatefromjpeg')) && (! class_exists('\\Imagick'))) { $ck_funcs[1]['status'] = false; $ck_funcs[1]['help'] = t('Error: GD PHP module with JPEG support or ImageMagick graphics library required but not installed.'); } -- cgit v1.2.3 From 1ca558f011b21b0a493d294501f530e57bdd574e Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 20 Sep 2018 13:22:41 +0200 Subject: move connection filtering setting from network to connections, provide a link to settings in the navbar if present for a module and some code optimisation --- Zotlabs/Module/Connections.php | 21 ++++++++------ Zotlabs/Module/Settings/Connections.php | 51 +++++++++++++++++++++++++++++++++ Zotlabs/Module/Settings/Network.php | 14 ++------- 3 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 Zotlabs/Module/Settings/Connections.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index cecada769..0e5f1dfe2 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -1,6 +1,7 @@ (($searching) ? t('Connections search') . ": '" . $search . "'" : ""), '$submit' => t('Find'), '$edit' => t('Edit'), - '$cmd' => \App::$cmd, + '$cmd' => App::$cmd, '$contacts' => $contacts, '$paginate' => paginate($a), diff --git a/Zotlabs/Module/Settings/Connections.php b/Zotlabs/Module/Settings/Connections.php new file mode 100644 index 000000000..361d86ccb --- /dev/null +++ b/Zotlabs/Module/Settings/Connections.php @@ -0,0 +1,51 @@ + 'settings/connections', + '$form_security_token' => get_form_security_token("settings_connections"), + '$title' => t('Connections Settings'), + '$features' => process_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + + function get_features() { + $arr = [ + [ + 'connfilter', + t('Connection Filtering'), + t('Filter incoming posts from connections based on keywords/content'), + false, + get_config('feature_lock','connfilter') + ] + ]; + + return $arr; + + } + +} diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index 4e2e3915e..eaf11f3da 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -10,13 +10,7 @@ class Network { $features = self::get_features(); - foreach($features as $f) { - $k = $f[0]; - if(array_key_exists("feature_$k",$_POST)) - set_pconfig(local_channel(),'feature',$k, (string) $_POST["feature_$k"]); - else - set_pconfig(local_channel(),'feature', $k, ''); - } + process_features_post(local_channel(), $features, $_POST); build_sync_packet(); return; @@ -26,17 +20,13 @@ class Network { $features = self::get_features(); - foreach($features as $f) { - $arr[] = array('feature_' . $f[0],$f[1],((intval(feature_enabled(local_channel(),$f[0]))) ? "1" : ''),$f[2],array(t('Off'),t('On'))); - } - $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( '$action_url' => 'settings/network', '$form_security_token' => get_form_security_token("settings_network"), '$title' => t('Activity Settings'), - '$features' => $arr, + '$features' => process_features_get(local_channel(), $features), '$submit' => t('Submit') )); -- cgit v1.2.3 From 369f34b2d122c7bd22522101fc9e4ce0f597a04e Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 20 Sep 2018 13:25:47 +0200 Subject: remove connection filter from network settings --- Zotlabs/Module/Settings/Network.php | 8 -------- 1 file changed, 8 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index eaf11f3da..1e39121c8 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -98,14 +98,6 @@ class Network { t('Show friend and connection suggestions'), false, get_config('feature_lock','suggest') - ], - - [ - 'connfilter', - t('Connection Filtering'), - t('Filter incoming posts from connections based on keywords/content'), - false, - get_config('feature_lock','connfilter') ] ]; -- cgit v1.2.3 From 3cc66b68162a82493cd68d369e4f0cbb01f941d0 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 20 Sep 2018 16:07:32 -0700 Subject: bookmarks fail to sync --- Zotlabs/Module/Bookmarks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php index cea0d9759..cee86a47d 100644 --- a/Zotlabs/Module/Bookmarks.php +++ b/Zotlabs/Module/Bookmarks.php @@ -59,7 +59,7 @@ class Bookmarks extends \Zotlabs\Web\Controller { killme(); } - function get() { + function get() { if(! local_channel()) { notice( t('Permission denied.') . EOL); return; -- cgit v1.2.3 From 5525f082e64bb942f8aae97d4976ea1ec0aa91ec Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 20 Sep 2018 22:43:01 -0700 Subject: remove bbcode from event hovertip --- Zotlabs/Module/Cal.php | 2 ++ Zotlabs/Module/Events.php | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index 87c13ef4e..3809064b0 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -6,6 +6,7 @@ require_once('include/bbcode.php'); require_once('include/datetime.php'); require_once('include/event.php'); require_once('include/items.php'); +require_once('include/html2plain.php'); class Cal extends \Zotlabs\Web\Controller { @@ -293,6 +294,7 @@ class Cal extends \Zotlabs\Web\Controller { } $html = format_event_html($rr); $rr['desc'] = zidify_links(smilies(bbcode($rr['desc']))); + $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8'); $rr['location'] = zidify_links(smilies(bbcode($rr['location']))); $events[] = array( 'id'=>$rr['id'], diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php index 33c8b8249..2115edde5 100644 --- a/Zotlabs/Module/Events.php +++ b/Zotlabs/Module/Events.php @@ -6,7 +6,7 @@ require_once('include/bbcode.php'); require_once('include/datetime.php'); require_once('include/event.php'); require_once('include/items.php'); - +require_once('include/html2plain.php'); class Events extends \Zotlabs\Web\Controller { @@ -641,6 +641,7 @@ class Events extends \Zotlabs\Web\Controller { } $html = format_event_html($rr); $rr['desc'] = zidify_links(smilies(bbcode($rr['desc']))); + $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8'); $rr['location'] = zidify_links(smilies(bbcode($rr['location']))); $events[] = array( 'id'=>$rr['id'], @@ -659,8 +660,6 @@ class Events extends \Zotlabs\Web\Controller { 'html'=>$html, 'plink' => array($rr['plink'],t('Link to Source'),'',''), ); - - } } -- cgit v1.2.3 From ba49e6a5889ffbb91ce783a00334d2b6221c42b7 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 20 Sep 2018 22:46:47 -0700 Subject: don't double encode --- Zotlabs/Module/Cal.php | 2 +- Zotlabs/Module/Events.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index 3809064b0..14c109515 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -294,7 +294,7 @@ class Cal extends \Zotlabs\Web\Controller { } $html = format_event_html($rr); $rr['desc'] = zidify_links(smilies(bbcode($rr['desc']))); - $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8'); + $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8',false); $rr['location'] = zidify_links(smilies(bbcode($rr['location']))); $events[] = array( 'id'=>$rr['id'], diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php index 2115edde5..213fa6bff 100644 --- a/Zotlabs/Module/Events.php +++ b/Zotlabs/Module/Events.php @@ -641,7 +641,7 @@ class Events extends \Zotlabs\Web\Controller { } $html = format_event_html($rr); $rr['desc'] = zidify_links(smilies(bbcode($rr['desc']))); - $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8'); + $rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8',false); $rr['location'] = zidify_links(smilies(bbcode($rr['location']))); $events[] = array( 'id'=>$rr['id'], -- cgit v1.2.3 From 6f43468724fccec3b37b7411a5ecb45a3ebe2e0b Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 21 Sep 2018 15:08:02 +0200 Subject: compare strpos() result against false --- Zotlabs/Lib/Apps.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 905a20ee0..b35eb9844 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -388,9 +388,10 @@ class Apps { // This will catch somebody clicking on a system "available" app that hasn't had the path macros replaced // and they are allowed to see the app - if(strpos($papp['url'],'$baseurl') || strpos($papp['url'],'$nick') || strpos($papp['photo'],'$baseurl') || strpos($papp['photo'],'$nick')) { + if(strpos($papp['url'],'$baseurl') !== false || strpos($papp['url'],'$nick') !== false || strpos($papp['photo'],'$baseurl') !== false || strpos($papp['photo'],'$nick') !== false) { $view_channel = local_channel(); if(! $view_channel) { + $sys = get_sys_channel(); $view_channel = $sys['channel_id']; } -- cgit v1.2.3 From 9638bf2b1eeb805b27eaf2f2e1e8a09bfd5c5514 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 21 Sep 2018 20:23:31 +0200 Subject: provide a return path from settings pages --- Zotlabs/Lib/Apps.php | 3 ++- Zotlabs/Module/Settings/Connections.php | 2 ++ Zotlabs/Module/Settings/Network.php | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index b35eb9844..010947467 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -524,7 +524,8 @@ class Apps { '$add' => t('Add to app-tray'), '$remove' => t('Remove from app-tray'), '$add_nav' => t('Pin to navbar'), - '$remove_nav' => t('Unpin from navbar') + '$remove_nav' => t('Unpin from navbar'), + '$rpath' => z_root() . '/apps' )); } diff --git a/Zotlabs/Module/Settings/Connections.php b/Zotlabs/Module/Settings/Connections.php index 361d86ccb..425409502 100644 --- a/Zotlabs/Module/Settings/Connections.php +++ b/Zotlabs/Module/Settings/Connections.php @@ -19,10 +19,12 @@ class Connections { function get() { $features = self::get_features(); + $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( + '$rpath' => $rpath, '$action_url' => 'settings/connections', '$form_security_token' => get_form_security_token("settings_connections"), '$title' => t('Connections Settings'), diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index 1e39121c8..a2e606565 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -19,10 +19,12 @@ class Network { function get() { $features = self::get_features(); + $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( + '$rpath' => $rpath, '$action_url' => 'settings/network', '$form_security_token' => get_form_security_token("settings_network"), '$title' => t('Activity Settings'), -- cgit v1.2.3 From 4484985c2d48d8256ae114d55a8f4e6db0303425 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 21 Sep 2018 21:37:00 +0200 Subject: add file --- Zotlabs/Module/Settings/Editor.php | 120 +++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 Zotlabs/Module/Settings/Editor.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php new file mode 100644 index 000000000..a87f31fe7 --- /dev/null +++ b/Zotlabs/Module/Settings/Editor.php @@ -0,0 +1,120 @@ + $rpath, + '$action_url' => 'settings/editor', + '$form_security_token' => get_form_security_token("settings_editor"), + '$title' => t('Editor Settings'), + '$features' => process_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + + function get_features() { + $arr = [ + + [ + 'large_photos', + t('Large Photos'), + t('Include large (1024px) photo thumbnails in posts. If not enabled, use small (640px) photo thumbnails'), + false, + get_config('feature_lock','large_photos'), + ], + + [ + //TODO: This should be its own app + 'channel_sources', + t('Channel Sources'), + t('Automatically import channel content from other channels or feeds'), + false, + get_config('feature_lock','channel_sources'), + ], + + [ + 'content_encrypt', + t('Even More Encryption'), + t('Allow optional encryption of content end-to-end with a shared secret key'), + false, + get_config('feature_lock','content_encrypt'), + ], + + [ + 'consensus_tools', + t('Enable Voting Tools'), + t('Provide a class of post which others can vote on'), + false, + get_config('feature_lock','consensus_tools'), + ], + + [ + 'disable_comments', + t('Disable Comments'), + t('Provide the option to disable comments for a post'), + false, + get_config('feature_lock','disable_comments'), + ], + + [ + 'delayed_posting', + t('Delayed Posting'), + t('Allow posts to be published at a later date'), + false, + get_config('feature_lock','delayed_posting'), + ], + + [ + 'content_expire', + t('Content Expiration'), + t('Remove posts/comments and/or private messages at a future time'), + false, + get_config('feature_lock','content_expire'), + ], + + [ + 'suppress_duplicates', + t('Suppress Duplicate Posts/Comments'), + t('Prevent posts with identical content to be published with less than two minutes in between submissions.'), + true, + get_config('feature_lock','suppress_duplicates'), + ], + + [ + 'auto_save_draft', + t('Auto-save drafts of posts and comments'), + t('Automatically saves post and comment drafts in local browser storage to help prevent accidental loss of compositions'), + true, + get_config('feature_lock','auto_save_draft'), + ] + + ]; + + return $arr; + + } + +} -- cgit v1.2.3 From ed00d1b2e3895f5feb0767d1b002f7be08797379 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Sat, 22 Sep 2018 10:44:51 +0200 Subject: Page meta properties --- Zotlabs/Web/HttpMeta.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/HttpMeta.php b/Zotlabs/Web/HttpMeta.php index 469a9ed8b..ceaa82162 100644 --- a/Zotlabs/Web/HttpMeta.php +++ b/Zotlabs/Web/HttpMeta.php @@ -54,8 +54,19 @@ class HttpMeta { } } if($this->check_required()) { + $arrayproperties = [ 'og:image' ]; foreach($this->og as $k => $v) { - $o .= '' . "\r\n" ; + if (in_array($k,$arrayproperties)) { + if (is_array($v)) { + foreach ($v as $v2) { + $o .= '' . "\r\n" ; + } + } else { + $o .= '' . "\r\n" ; + } + } else { + $o .= '' . "\r\n" ; + } } } if($o) @@ -63,4 +74,4 @@ class HttpMeta { return $o; } -} \ No newline at end of file +} -- cgit v1.2.3 From 1e5405ccaf3ddff88653cc34a04cfce9b7102891 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 22 Sep 2018 13:32:42 +0200 Subject: appification of sources --- Zotlabs/Module/Settings/Editor.php | 9 --------- Zotlabs/Module/Sources.php | 22 +++++++++++++++------- 2 files changed, 15 insertions(+), 16 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php index a87f31fe7..92775f154 100644 --- a/Zotlabs/Module/Settings/Editor.php +++ b/Zotlabs/Module/Settings/Editor.php @@ -46,15 +46,6 @@ class Editor { get_config('feature_lock','large_photos'), ], - [ - //TODO: This should be its own app - 'channel_sources', - t('Channel Sources'), - t('Automatically import channel content from other channels or feeds'), - false, - get_config('feature_lock','channel_sources'), - ], - [ 'content_encrypt', t('Even More Encryption'), diff --git a/Zotlabs/Module/Sources.php b/Zotlabs/Module/Sources.php index 2a2fa1835..5d05244a7 100644 --- a/Zotlabs/Module/Sources.php +++ b/Zotlabs/Module/Sources.php @@ -1,15 +1,18 @@ Sources App (Not Installed):
'; + $o .= t('Automatically import channel content from other channels or feeds'); + return $o; + } // list sources if(argc() == 1) { -- cgit v1.2.3 From 45078dda825d6412f755e2727e25c027ca48c1e9 Mon Sep 17 00:00:00 2001 From: Mario Date: Sat, 22 Sep 2018 19:48:17 +0200 Subject: introduce profile settings and provide a way for modules without an app to still be able to link to its settings page from the navbar --- Zotlabs/Module/Profiles.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php index 202ee462a..de4075ba9 100644 --- a/Zotlabs/Module/Profiles.php +++ b/Zotlabs/Module/Profiles.php @@ -8,8 +8,8 @@ require_once('include/selectors.php'); class Profiles extends \Zotlabs\Web\Controller { function init() { - - nav_set_selected('Profiles'); + + nav_set_selected('Profiles', 'settings/profiles'); if(! local_channel()) { return; -- cgit v1.2.3 From 65be3de200040bad89a4b5bc78fb6ff72bfffaad Mon Sep 17 00:00:00 2001 From: Mario Date: Sat, 22 Sep 2018 20:10:48 +0200 Subject: add files and settings for channel manager --- Zotlabs/Module/Manage.php | 2 +- Zotlabs/Module/Settings/Manage.php | 55 +++++++++++++++++++++++++++ Zotlabs/Module/Settings/Profiles.php | 72 ++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 Zotlabs/Module/Settings/Manage.php create mode 100644 Zotlabs/Module/Settings/Profiles.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Manage.php b/Zotlabs/Module/Manage.php index 2c88a4df0..ea24bbf61 100644 --- a/Zotlabs/Module/Manage.php +++ b/Zotlabs/Module/Manage.php @@ -11,7 +11,7 @@ class Manage extends \Zotlabs\Web\Controller { return; } - nav_set_selected('Channel Manager'); + nav_set_selected('Channel Manager', 'settings/manage'); require_once('include/security.php'); diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php new file mode 100644 index 000000000..f10f4d502 --- /dev/null +++ b/Zotlabs/Module/Settings/Manage.php @@ -0,0 +1,55 @@ + $rpath, + '$action_url' => 'settings/manage', + '$form_security_token' => get_form_security_token("settings_manage"), + '$title' => t('Channel Manager Settings'), + '$features' => process_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + + function get_features() { + $arr = [ + + [ + 'nav_channel_select', + t('Navigation Channel Select'), + t('Change channels directly from within the navigation dropdown menu'), + true, + get_config('feature_lock','nav_channel_select'), + ] + + ]; + + return $arr; + + } + +} diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php new file mode 100644 index 000000000..801bb7b10 --- /dev/null +++ b/Zotlabs/Module/Settings/Profiles.php @@ -0,0 +1,72 @@ + $rpath, + '$action_url' => 'settings/profiles', + '$form_security_token' => get_form_security_token("settings_profiles"), + '$title' => t('Profile Settings'), + '$features' => process_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + + function get_features() { + $arr = [ + + [ + 'advanced_profiles', + t('Advanced Profiles'), + t('Additional profile sections and selections'), + false, + get_config('feature_lock','advanced_profiles'), + ], + + [ + 'profile_export', + t('Profile Import/Export'), + t('Save and load profile details across sites/channels'), + false, + get_config('feature_lock','profile_export'), + ], + + [ + 'multi_profiles', + t('Multiple Profiles'), + t('Ability to create multiple profiles'), + false, + get_config('feature_lock','multi_profiles'), + ] + + + ]; + + return $arr; + + } + +} -- cgit v1.2.3 From b296a73330267ea0e7444f1ab66b546ecfef02af Mon Sep 17 00:00:00 2001 From: Mario Date: Sat, 22 Sep 2018 20:15:34 +0200 Subject: this should be off by default --- Zotlabs/Module/Settings/Manage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php index f10f4d502..e13017d6b 100644 --- a/Zotlabs/Module/Settings/Manage.php +++ b/Zotlabs/Module/Settings/Manage.php @@ -42,7 +42,7 @@ class Manage { 'nav_channel_select', t('Navigation Channel Select'), t('Change channels directly from within the navigation dropdown menu'), - true, + false, get_config('feature_lock','nav_channel_select'), ] -- cgit v1.2.3 From 9e22ec267c0020e27e4b1cdf5da23b442529da6a Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 23 Sep 2018 01:11:06 +0200 Subject: keep the features in the central array but sort them by module name --- Zotlabs/Module/Settings/Connections.php | 23 ++-------- Zotlabs/Module/Settings/Editor.php | 81 ++------------------------------- Zotlabs/Module/Settings/Manage.php | 25 ++-------- Zotlabs/Module/Settings/Network.php | 81 ++------------------------------- Zotlabs/Module/Settings/Profiles.php | 42 ++--------------- 5 files changed, 20 insertions(+), 232 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Connections.php b/Zotlabs/Module/Settings/Connections.php index 425409502..f3638862b 100644 --- a/Zotlabs/Module/Settings/Connections.php +++ b/Zotlabs/Module/Settings/Connections.php @@ -8,9 +8,9 @@ class Connections { function post() { check_form_security_token_redirectOnErr('/settings/connections', 'settings_connections'); - $features = self::get_features(); + $features = get_module_features('connections'); - process_features_post(local_channel(), $features, $_POST); + process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); return; @@ -18,7 +18,7 @@ class Connections { function get() { - $features = self::get_features(); + $features = get_module_features('connections'); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); @@ -28,26 +28,11 @@ class Connections { '$action_url' => 'settings/connections', '$form_security_token' => get_form_security_token("settings_connections"), '$title' => t('Connections Settings'), - '$features' => process_features_get(local_channel(), $features), + '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); return $o; } - function get_features() { - $arr = [ - [ - 'connfilter', - t('Connection Filtering'), - t('Filter incoming posts from connections based on keywords/content'), - false, - get_config('feature_lock','connfilter') - ] - ]; - - return $arr; - - } - } diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php index 92775f154..514417e49 100644 --- a/Zotlabs/Module/Settings/Editor.php +++ b/Zotlabs/Module/Settings/Editor.php @@ -8,9 +8,9 @@ class Editor { function post() { check_form_security_token_redirectOnErr('/settings/editor', 'settings_editor'); - $features = self::get_features(); + $features = get_module_features('editor'); - process_features_post(local_channel(), $features, $_POST); + process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); return; @@ -18,7 +18,7 @@ class Editor { function get() { - $features = self::get_features(); + $features = get_module_features('editor'); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); @@ -28,84 +28,11 @@ class Editor { '$action_url' => 'settings/editor', '$form_security_token' => get_form_security_token("settings_editor"), '$title' => t('Editor Settings'), - '$features' => process_features_get(local_channel(), $features), + '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); return $o; } - function get_features() { - $arr = [ - - [ - 'large_photos', - t('Large Photos'), - t('Include large (1024px) photo thumbnails in posts. If not enabled, use small (640px) photo thumbnails'), - false, - get_config('feature_lock','large_photos'), - ], - - [ - 'content_encrypt', - t('Even More Encryption'), - t('Allow optional encryption of content end-to-end with a shared secret key'), - false, - get_config('feature_lock','content_encrypt'), - ], - - [ - 'consensus_tools', - t('Enable Voting Tools'), - t('Provide a class of post which others can vote on'), - false, - get_config('feature_lock','consensus_tools'), - ], - - [ - 'disable_comments', - t('Disable Comments'), - t('Provide the option to disable comments for a post'), - false, - get_config('feature_lock','disable_comments'), - ], - - [ - 'delayed_posting', - t('Delayed Posting'), - t('Allow posts to be published at a later date'), - false, - get_config('feature_lock','delayed_posting'), - ], - - [ - 'content_expire', - t('Content Expiration'), - t('Remove posts/comments and/or private messages at a future time'), - false, - get_config('feature_lock','content_expire'), - ], - - [ - 'suppress_duplicates', - t('Suppress Duplicate Posts/Comments'), - t('Prevent posts with identical content to be published with less than two minutes in between submissions.'), - true, - get_config('feature_lock','suppress_duplicates'), - ], - - [ - 'auto_save_draft', - t('Auto-save drafts of posts and comments'), - t('Automatically saves post and comment drafts in local browser storage to help prevent accidental loss of compositions'), - true, - get_config('feature_lock','auto_save_draft'), - ] - - ]; - - return $arr; - - } - } diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php index e13017d6b..841e58be3 100644 --- a/Zotlabs/Module/Settings/Manage.php +++ b/Zotlabs/Module/Settings/Manage.php @@ -8,9 +8,9 @@ class Manage { function post() { check_form_security_token_redirectOnErr('/settings/manage', 'settings_manage'); - $features = self::get_features(); + $features = get_module_features('manage'); - process_features_post(local_channel(), $features, $_POST); + process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); return; @@ -18,7 +18,7 @@ class Manage { function get() { - $features = self::get_features(); + $features = get_module_features('manage'); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); @@ -28,28 +28,11 @@ class Manage { '$action_url' => 'settings/manage', '$form_security_token' => get_form_security_token("settings_manage"), '$title' => t('Channel Manager Settings'), - '$features' => process_features_get(local_channel(), $features), + '$features' => process__module_features_get(local_channel(), $features), '$submit' => t('Submit') )); return $o; } - function get_features() { - $arr = [ - - [ - 'nav_channel_select', - t('Navigation Channel Select'), - t('Change channels directly from within the navigation dropdown menu'), - false, - get_config('feature_lock','nav_channel_select'), - ] - - ]; - - return $arr; - - } - } diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index a2e606565..bc0ba7143 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -8,9 +8,9 @@ class Network { function post() { check_form_security_token_redirectOnErr('/settings/network', 'settings_network'); - $features = self::get_features(); + $features = get_module_features('network'); - process_features_post(local_channel(), $features, $_POST); + process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); return; @@ -18,7 +18,7 @@ class Network { function get() { - $features = self::get_features(); + $features = get_module_features('network'); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); @@ -28,84 +28,11 @@ class Network { '$action_url' => 'settings/network', '$form_security_token' => get_form_security_token("settings_network"), '$title' => t('Activity Settings'), - '$features' => process_features_get(local_channel(), $features), + '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); return $o; } - function get_features() { - $arr = [ - - [ - 'archives', - t('Search by Date'), - t('Ability to select posts by date ranges'), - false, - get_config('feature_lock','archives') - ], - - [ - 'savedsearch', - t('Saved Searches'), - t('Save search terms for re-use'), - false, - get_config('feature_lock','savedsearch') - ], - - [ - 'order_tab', - t('Alternate Stream Order'), - t('Ability to order the stream by last post date, last comment date or unthreaded activities'), - false, - get_config('feature_lock','order_tab') - ], - - [ - 'name_tab', - t('Contact Filter'), - t('Ability to display only posts of a selected contact'), - false, - get_config('feature_lock','name_tab') - ], - - [ - 'forums_tab', - t('Forum Filter'), - t('Ability to display only posts of a specific forum'), - false, - get_config('feature_lock','forums_tab') - ], - - [ - 'personal_tab', - t('Personal Posts Filter'), - t('Ability to display only posts that you\'ve interacted on'), - false, - get_config('feature_lock','personal_tab') - ], - - [ - 'affinity', - t('Affinity Tool'), - t('Filter stream activity by depth of relationships'), - false, - get_config('feature_lock','affinity') - ], - - [ - 'suggest', - t('Suggest Channels'), - t('Show friend and connection suggestions'), - false, - get_config('feature_lock','suggest') - ] - - ]; - - return $arr; - - } - } diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php index 801bb7b10..a22a540da 100644 --- a/Zotlabs/Module/Settings/Profiles.php +++ b/Zotlabs/Module/Settings/Profiles.php @@ -8,9 +8,9 @@ class Profiles { function post() { check_form_security_token_redirectOnErr('/settings/profiles', 'settings_profiles'); - $features = self::get_features(); + $features = get_module_features('profiles'); - process_features_post(local_channel(), $features, $_POST); + process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); return; @@ -18,7 +18,7 @@ class Profiles { function get() { - $features = self::get_features(); + $features = get_module_features('profiles'); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); @@ -28,45 +28,11 @@ class Profiles { '$action_url' => 'settings/profiles', '$form_security_token' => get_form_security_token("settings_profiles"), '$title' => t('Profile Settings'), - '$features' => process_features_get(local_channel(), $features), + '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); return $o; } - function get_features() { - $arr = [ - - [ - 'advanced_profiles', - t('Advanced Profiles'), - t('Additional profile sections and selections'), - false, - get_config('feature_lock','advanced_profiles'), - ], - - [ - 'profile_export', - t('Profile Import/Export'), - t('Save and load profile details across sites/channels'), - false, - get_config('feature_lock','profile_export'), - ], - - [ - 'multi_profiles', - t('Multiple Profiles'), - t('Ability to create multiple profiles'), - false, - get_config('feature_lock','multi_profiles'), - ] - - - ]; - - return $arr; - - } - } -- cgit v1.2.3 From 1f1d5b9181dd7a9800a2d5c596d8da0f906c53e3 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 23 Sep 2018 17:52:32 +0200 Subject: provide settings for mod photo and make it slightly simpler to create new module settings --- Zotlabs/Module/Settings/Connections.php | 17 +++++++++++------ Zotlabs/Module/Settings/Editor.php | 17 +++++++++++------ Zotlabs/Module/Settings/Manage.php | 19 ++++++++++++------- Zotlabs/Module/Settings/Network.php | 17 +++++++++++------ Zotlabs/Module/Settings/Profiles.php | 19 ++++++++++++------- 5 files changed, 57 insertions(+), 32 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Connections.php b/Zotlabs/Module/Settings/Connections.php index f3638862b..70b4daa42 100644 --- a/Zotlabs/Module/Settings/Connections.php +++ b/Zotlabs/Module/Settings/Connections.php @@ -6,9 +6,12 @@ namespace Zotlabs\Module\Settings; class Connections { function post() { - check_form_security_token_redirectOnErr('/settings/connections', 'settings_connections'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - $features = get_module_features('connections'); + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); @@ -17,16 +20,18 @@ class Connections { } function get() { - - $features = get_module_features('connections'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + $features = get_module_features($module); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( '$rpath' => $rpath, - '$action_url' => 'settings/connections', - '$form_security_token' => get_form_security_token("settings_connections"), + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Connections Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php index 514417e49..93e3ce602 100644 --- a/Zotlabs/Module/Settings/Editor.php +++ b/Zotlabs/Module/Settings/Editor.php @@ -6,9 +6,12 @@ namespace Zotlabs\Module\Settings; class Editor { function post() { - check_form_security_token_redirectOnErr('/settings/editor', 'settings_editor'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - $features = get_module_features('editor'); + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); @@ -17,16 +20,18 @@ class Editor { } function get() { - - $features = get_module_features('editor'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + $features = get_module_features($module); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( '$rpath' => $rpath, - '$action_url' => 'settings/editor', - '$form_security_token' => get_form_security_token("settings_editor"), + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Editor Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php index 841e58be3..15d3216e9 100644 --- a/Zotlabs/Module/Settings/Manage.php +++ b/Zotlabs/Module/Settings/Manage.php @@ -6,9 +6,12 @@ namespace Zotlabs\Module\Settings; class Manage { function post() { - check_form_security_token_redirectOnErr('/settings/manage', 'settings_manage'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - $features = get_module_features('manage'); + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); @@ -17,18 +20,20 @@ class Manage { } function get() { - - $features = get_module_features('manage'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + $features = get_module_features($module); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( '$rpath' => $rpath, - '$action_url' => 'settings/manage', - '$form_security_token' => get_form_security_token("settings_manage"), + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Channel Manager Settings'), - '$features' => process__module_features_get(local_channel(), $features), + '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index bc0ba7143..c51b780f1 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -6,9 +6,12 @@ namespace Zotlabs\Module\Settings; class Network { function post() { - check_form_security_token_redirectOnErr('/settings/network', 'settings_network'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - $features = get_module_features('network'); + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); @@ -17,16 +20,18 @@ class Network { } function get() { - - $features = get_module_features('network'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + $features = get_module_features($module); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( '$rpath' => $rpath, - '$action_url' => 'settings/network', - '$form_security_token' => get_form_security_token("settings_network"), + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Activity Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php index a22a540da..78dc0160e 100644 --- a/Zotlabs/Module/Settings/Profiles.php +++ b/Zotlabs/Module/Settings/Profiles.php @@ -6,9 +6,12 @@ namespace Zotlabs\Module\Settings; class Profiles { function post() { - check_form_security_token_redirectOnErr('/settings/profiles', 'settings_profiles'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); - $features = get_module_features('profiles'); + $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); @@ -17,17 +20,19 @@ class Profiles { } function get() { - - $features = get_module_features('profiles'); + + $module = substr(strrchr(strtolower(static::class), '\\'), 1); + + $features = get_module_features($module); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( '$rpath' => $rpath, - '$action_url' => 'settings/profiles', - '$form_security_token' => get_form_security_token("settings_profiles"), - '$title' => t('Profile Settings'), + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), + '$title' => t('Profiles Settings'), '$features' => process_module_features_get(local_channel(), $features), '$submit' => t('Submit') )); -- cgit v1.2.3 From 781fdaafcd6a8086b76409b0a39d8edbca2e04c9 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 23 Sep 2018 19:18:05 +0200 Subject: settings for events and cdav calendar --- Zotlabs/Module/Cal.php | 2 +- Zotlabs/Module/Cdav.php | 4 +++- Zotlabs/Module/Events.php | 6 +++-- Zotlabs/Module/Settings/Calendar.php | 43 ++++++++++++++++++++++++++++++++++++ Zotlabs/Module/Settings/Channel.php | 2 +- Zotlabs/Module/Settings/Events.php | 43 ++++++++++++++++++++++++++++++++++++ Zotlabs/Module/Settings/Photos.php | 43 ++++++++++++++++++++++++++++++++++++ 7 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 Zotlabs/Module/Settings/Calendar.php create mode 100644 Zotlabs/Module/Settings/Events.php create mode 100644 Zotlabs/Module/Settings/Photos.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index 14c109515..2962d31fd 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -75,7 +75,7 @@ class Cal extends \Zotlabs\Web\Controller { $sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event'); - $first_day = get_pconfig(local_channel(),'system','cal_first_day'); + $first_day = feature_enabled($channel['channel_id'], 'cal_first_day'); $first_day = (($first_day) ? $first_day : 0); $htpl = get_markup_template('event_head.tpl'); diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index bff308dfa..7142615d5 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -850,6 +850,8 @@ class Cdav extends Controller { return $o; } + App::$profile_uid = local_channel(); + $channel = App::get_channel(); $principalUri = 'principals/' . $channel['channel_address']; @@ -905,7 +907,7 @@ class Cdav extends Controller { $sources = rtrim($sources, ', '); - $first_day = get_pconfig(local_channel(),'system','cal_first_day'); + $first_day = feature_enabled(local_channel(), 'cal_first_day'); $first_day = (($first_day) ? $first_day : 0); $title = ['title', t('Event title')]; diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php index 213fa6bff..b63921ce3 100644 --- a/Zotlabs/Module/Events.php +++ b/Zotlabs/Module/Events.php @@ -271,8 +271,10 @@ class Events extends \Zotlabs\Web\Controller { notice( t('Permission denied.') . EOL); return; } - + + \App::$profile_uid = local_channel(); nav_set_selected('Events'); + if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) { $r = q("update event set dismissed = 1 where id = %d and uid = %d", @@ -288,7 +290,7 @@ class Events extends \Zotlabs\Web\Controller { ); } - $first_day = get_pconfig(local_channel(),'system','cal_first_day'); + $first_day = feature_enabled(local_channel(), 'cal_first_day'); $first_day = (($first_day) ? $first_day : 0); $htpl = get_markup_template('event_head.tpl'); diff --git a/Zotlabs/Module/Settings/Calendar.php b/Zotlabs/Module/Settings/Calendar.php new file mode 100644 index 000000000..b3a611cdf --- /dev/null +++ b/Zotlabs/Module/Settings/Calendar.php @@ -0,0 +1,43 @@ + $rpath, + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), + '$title' => t('CalDAV Settings'), + '$features' => process_module_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + +} diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 3a6e03588..6fea970fe 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -622,7 +622,7 @@ class Channel { '$removeme' => t('Remove Channel'), '$removechannel' => t('Remove this channel.'), '$firefoxshare' => t('Firefox Share $Projectname provider'), - '$cal_first_day' => array('first_day', t('Start calendar week on Monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no), + )); call_hooks('settings_form',$o); diff --git a/Zotlabs/Module/Settings/Events.php b/Zotlabs/Module/Settings/Events.php new file mode 100644 index 000000000..fcb4441e1 --- /dev/null +++ b/Zotlabs/Module/Settings/Events.php @@ -0,0 +1,43 @@ + $rpath, + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), + '$title' => t('Events Settings'), + '$features' => process_module_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + +} diff --git a/Zotlabs/Module/Settings/Photos.php b/Zotlabs/Module/Settings/Photos.php new file mode 100644 index 000000000..f403b4d38 --- /dev/null +++ b/Zotlabs/Module/Settings/Photos.php @@ -0,0 +1,43 @@ + $rpath, + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), + '$title' => t('Photos Settings'), + '$features' => process_module_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + +} -- cgit v1.2.3 From a1d1d5dba7c975e00bcf8c8dfc8e6ccd13f3df90 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 23 Sep 2018 19:40:52 +0200 Subject: use different settings for cal_first_day in events and cdav/calendar. This is a tradeoff. It would be better to have one setting for both but if we want to preserve the *all settings* view, this would break its functionality --- Zotlabs/Module/Cal.php | 2 +- Zotlabs/Module/Events.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index 2962d31fd..70098a2a1 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -75,7 +75,7 @@ class Cal extends \Zotlabs\Web\Controller { $sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event'); - $first_day = feature_enabled($channel['channel_id'], 'cal_first_day'); + $first_day = feature_enabled($channel['channel_id'], 'events_cal_first_day'); $first_day = (($first_day) ? $first_day : 0); $htpl = get_markup_template('event_head.tpl'); diff --git a/Zotlabs/Module/Events.php b/Zotlabs/Module/Events.php index b63921ce3..7e5204e62 100644 --- a/Zotlabs/Module/Events.php +++ b/Zotlabs/Module/Events.php @@ -290,7 +290,7 @@ class Events extends \Zotlabs\Web\Controller { ); } - $first_day = feature_enabled(local_channel(), 'cal_first_day'); + $first_day = feature_enabled(local_channel(), 'events_cal_first_day'); $first_day = (($first_day) ? $first_day : 0); $htpl = get_markup_template('event_head.tpl'); -- cgit v1.2.3 From d83fe9d417d8e7773e0f36b0605f79ab5eec07b7 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 23 Sep 2018 20:02:28 +0200 Subject: minor cleanup --- Zotlabs/Module/Settings/Channel.php | 2 -- 1 file changed, 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 6fea970fe..27a8e695d 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -154,7 +154,6 @@ class Channel { $adult = (($_POST['adult'] == 1) ? 1 : 0); $defpermcat = ((x($_POST,'defpermcat')) ? notags(trim($_POST['defpermcat'])) : 'default'); - $cal_first_day = (((x($_POST,'first_day')) && (intval($_POST['first_day']) == 1)) ? 1: 0); $mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : ''); $profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : ''); @@ -251,7 +250,6 @@ class Channel { set_pconfig(local_channel(),'system','evdays',$evdays); set_pconfig(local_channel(),'system','photo_path',$photo_path); set_pconfig(local_channel(),'system','attach_path',$attach_path); - set_pconfig(local_channel(),'system','cal_first_day',$cal_first_day); set_pconfig(local_channel(),'system','default_permcat',$defpermcat); set_pconfig(local_channel(),'system','email_notify_host',$mailhost); set_pconfig(local_channel(),'system','profile_assign',$profile_assign); -- cgit v1.2.3 From e735220691366fb29276dbc3f47ad0347c40aaf5 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 23 Sep 2018 20:54:36 +0200 Subject: only explain how to select a channel if there are channels to select --- Zotlabs/Module/Manage.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Manage.php b/Zotlabs/Module/Manage.php index ea24bbf61..20d5b0449 100644 --- a/Zotlabs/Module/Manage.php +++ b/Zotlabs/Module/Manage.php @@ -129,7 +129,7 @@ class Manage extends \Zotlabs\Web\Controller { } } - + $r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0", intval(get_account_id()) ); @@ -170,7 +170,7 @@ class Manage extends \Zotlabs\Web\Controller { '$header' => t('Channel Manager'), '$msg_selected' => t('Current Channel'), '$selected' => local_channel(), - '$desc' => t('Switch to one of your channels by selecting it.'), + '$desc' => ((count($channels) > 1 || $delegates) ? t('Switch to one of your channels by selecting it.') : ''), '$msg_default' => t('Default Channel'), '$msg_make_default' => t('Make Default'), '$create' => $create, -- cgit v1.2.3 From 995fc63f2caa6d735044b28caf03793f7c275eb1 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Sun, 23 Sep 2018 22:36:27 -0400 Subject: Add filters for addon/app installed checks and docs --- Zotlabs/Lib/Apps.php | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 010947467..4ee64f15e 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -532,7 +532,7 @@ class Apps { static public function app_install($uid,$app) { $app['uid'] = $uid; - if(self::app_installed($uid,$app)) + if(self::app_installed($uid,$app,true)) $x = self::app_update($app); else $x = self::app_store($app); @@ -660,33 +660,60 @@ class Apps { } } - static public function app_installed($uid,$app) { + 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'] : ''), intval($uid) ); + if (!$bypass_filter) { + $filter_arr = [ + 'uid'=>$uid, + 'app'=>$app, + 'installed'=>$r + ]; + call_hooks('app_installed_filter',$filter_arr); + $r = $filter_arr['installed']; + } return(($r) ? true : false); } - static public function addon_app_installed($uid,$app) { + static public function addon_app_installed($uid,$app,$bypass_filter=false) { $r = q("select id from app where app_plugin = '%s' and app_channel = %d limit 1", dbesc($app), intval($uid) ); + if (!$bypass_filter) { + $filter_arr = [ + 'uid'=>$uid, + 'app'=>$app, + 'installed'=>$r + ]; + call_hooks('addon_app_installed_filter',$filter_arr); + $r = $filter_arr['installed']; + } return(($r) ? true : false); } - static public function system_app_installed($uid,$app) { + static public function system_app_installed($uid,$app,$bypass_filter=false) { $r = q("select id from app where app_id = '%s' and app_channel = %d limit 1", dbesc(hash('whirlpool',$app)), intval($uid) ); + if (!$bypass_filter) { + $filter_arr = [ + 'uid'=>$uid, + 'app'=>$app, + 'installed'=>$r + ]; + call_hooks('system_app_installed_filter',$filter_arr); + $r = $filter_arr['installed']; + } return(($r) ? true : false); } -- cgit v1.2.3 From 7cadc30914041364663b947d787da6f8b980b894 Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 24 Sep 2018 09:33:52 +0200 Subject: settings for directory and set App::$profile_uid in directory if local_channel() --- Zotlabs/Module/Directory.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php index 8a7c6baf6..c29fa8326 100644 --- a/Zotlabs/Module/Directory.php +++ b/Zotlabs/Module/Directory.php @@ -12,13 +12,16 @@ class Directory extends \Zotlabs\Web\Controller { function init() { \App::set_pager_itemspage(60); - if(x($_GET,'ignore')) { + if(local_channel() && x($_GET,'ignore')) { q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ", intval(local_channel()), dbesc($_GET['ignore']) ); goaway(z_root() . '/directory?f=&suggest=1'); } + + if(local_channel()) + \App::$profile_uid = local_channel(); $observer = get_observer_hash(); $global_changed = false; @@ -55,6 +58,7 @@ class Directory extends \Zotlabs\Web\Controller { if($observer) set_xconfig($observer,'directory','pubforums',$pubforums); } + } function get() { -- cgit v1.2.3 From 85e06a77af7c81dab185b7a5757564215c41a2ed Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 24 Sep 2018 09:34:28 +0200 Subject: add file --- Zotlabs/Module/Settings/Directory.php | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Zotlabs/Module/Settings/Directory.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Directory.php b/Zotlabs/Module/Settings/Directory.php new file mode 100644 index 000000000..2682bcafc --- /dev/null +++ b/Zotlabs/Module/Settings/Directory.php @@ -0,0 +1,43 @@ + $rpath, + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), + '$title' => t('Directory Settings'), + '$features' => process_module_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + +} -- cgit v1.2.3 From c3aa15cc165730b6e67de580065ace255454dfb5 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 24 Sep 2018 11:46:18 +0200 Subject: appification of notes --- Zotlabs/Module/Notes.php | 41 ++++++++++++++++++++++++++++++++++------- Zotlabs/Widget/Notes.php | 14 ++++++++++---- 2 files changed, 44 insertions(+), 11 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php index e530e6ff4..cd383a6c2 100644 --- a/Zotlabs/Module/Notes.php +++ b/Zotlabs/Module/Notes.php @@ -1,13 +1,19 @@ true); if(array_key_exists('note_text',$_REQUEST)) { @@ -24,17 +30,38 @@ class Notes extends \Zotlabs\Web\Controller { } set_pconfig(local_channel(),'notes','text',$body); } - + // push updates to channel clones - + if((argc() > 1) && (argv(1) === 'sync')) { require_once('include/zot.php'); build_sync_packet(); } - + logger('notes saved.', LOGGER_DEBUG); json_return_and_die($ret); - + + } + + function get() { + + if(! local_channel()) + return EMPTY_STR; + + if(! Apps::system_app_installed(local_channel(), 'Notes')) { + //Do not display any associated widgets at this point + App::$pdl = EMPTY_STR; + + $o = 'Notes App (Not Installed):
'; + $o .= t('A simple notes app with a widget (note: notes are not encrypted)'); + return $o; + } + + $w = new \Zotlabs\Widget\Notes; + $arr = ['app' => true]; + + return $w->widget($arr); + } } diff --git a/Zotlabs/Widget/Notes.php b/Zotlabs/Widget/Notes.php index 5c83a550f..238008d81 100644 --- a/Zotlabs/Widget/Notes.php +++ b/Zotlabs/Widget/Notes.php @@ -2,20 +2,26 @@ namespace Zotlabs\Widget; +use Zotlabs\Lib\Apps; + class Notes { function widget($arr) { if(! local_channel()) - return ''; - if(! feature_enabled(local_channel(),'private_notes')) - return ''; + return EMPTY_STR; + + if(! Apps::system_app_installed(local_channel(), 'Notes')) + return EMPTY_STR; $text = get_pconfig(local_channel(),'notes','text'); - $o = replace_macros(get_markup_template('notes.tpl'), array( + $tpl = get_markup_template('notes.tpl'); + + $o = replace_macros($tpl, array( '$banner' => t('Notes'), '$text' => $text, '$save' => t('Save'), + '$app' => ((isset($arr['app'])) ? true : false) )); return $o; -- cgit v1.2.3 From 4c58a5cef278357c1bc31b76cfbd2719e3338398 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 25 Sep 2018 10:06:24 +0200 Subject: premium channel app --- Zotlabs/Module/Connect.php | 68 +++++++++++++++++++++++++++------------- Zotlabs/Widget/Settings_menu.php | 19 +---------- 2 files changed, 48 insertions(+), 39 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Connect.php b/Zotlabs/Module/Connect.php index cd43ea290..7194e7039 100644 --- a/Zotlabs/Module/Connect.php +++ b/Zotlabs/Module/Connect.php @@ -1,21 +1,21 @@ 1) $which = argv(1); else { notice( t('Requested profile is not available.') . EOL ); - \App::$error = 404; + App::$error = 404; return; } @@ -24,20 +24,32 @@ class Connect extends \Zotlabs\Web\Controller { ); if($r) - \App::$data['channel'] = $r[0]; + App::$data['channel'] = $r[0]; + + $channel_id = App::$data['channel']['channel_id']; + + if(! Apps::system_app_installed($channel_id, 'Premium Channel')) { + return; + } profile_load($which,''); } function post() { - if(! array_key_exists('channel', \App::$data)) + if(! array_key_exists('channel', App::$data)) + return; + + $channel_id = App::$data['channel']['channel_id']; + + if(! Apps::system_app_installed($channel_id, 'Premium Channel')) { return; + } - $edit = ((local_channel() && (local_channel() == \App::$data['channel']['channel_id'])) ? true : false); + $edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false); if($edit) { - $has_premium = ((\App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? 1 : 0); + $has_premium = ((App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? 1 : 0); $premium = (($_POST['premium']) ? intval($_POST['premium']) : 0); $text = escape_tags($_POST['text']); @@ -48,25 +60,25 @@ class Connect extends \Zotlabs\Web\Controller { intval(local_channel()) ); - \Zotlabs\Daemon\Master::Summon(array('Notifier','refresh_all',\App::$data['channel']['channel_id'])); + \Zotlabs\Daemon\Master::Summon(array('Notifier','refresh_all',$channel_id)); } - set_pconfig(\App::$data['channel']['channel_id'],'system','selltext',$text); + set_pconfig($channel_id,'system','selltext',$text); // reload the page completely to get fresh data - goaway(z_root() . '/' . \App::$query_string); + goaway(z_root() . '/' . App::$query_string); } $url = ''; - $observer = \App::get_observer(); + $observer = App::get_observer(); if(($observer) && ($_POST['submit'] === t('Continue'))) { if($observer['xchan_follow']) - $url = sprintf($observer['xchan_follow'],urlencode(channel_reddress(\App::$data['channel']))); + $url = sprintf($observer['xchan_follow'],urlencode(channel_reddress(App::$data['channel']))); if(! $url) { $r = q("select * from hubloc where hubloc_hash = '%s' order by hubloc_id desc limit 1", dbesc($observer['xchan_hash']) ); if($r) - $url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(channel_reddress(\App::$data['channel'])); + $url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(channel_reddress(App::$data['channel'])); } } if($url) @@ -79,17 +91,31 @@ class Connect extends \Zotlabs\Web\Controller { function get() { + + if(! array_key_exists('channel', App::$data)) + return; + + $channel_id = App::$data['channel']['channel_id']; + + if(! Apps::system_app_installed($channel_id, 'Premium Channel')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'Premium Channel App (Not Installed):
'; + $o .= t('Allows you to set restrictions and terms on those that connect with your channel'); + return $o; + } - $edit = ((local_channel() && (local_channel() == \App::$data['channel']['channel_id'])) ? true : false); + $edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false); - $text = get_pconfig(\App::$data['channel']['channel_id'],'system','selltext'); + $text = get_pconfig($channel_id,'system','selltext'); if($edit) { $o = replace_macros(get_markup_template('sellpage_edit.tpl'),array( '$header' => t('Premium Channel Setup'), - '$address' => \App::$data['channel']['channel_address'], - '$premium' => array('premium', t('Enable premium channel connection restrictions'),((\App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? '1' : ''),''), + '$address' => App::$data['channel']['channel_address'], + '$premium' => array('premium', t('Enable premium channel connection restrictions'),((App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? '1' : ''),''), '$lbl_about' => t('Please enter your restrictions or conditions, such as paypal receipt, usage guidelines, etc.'), '$text' => $text, '$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'), @@ -107,7 +133,7 @@ class Connect extends \Zotlabs\Web\Controller { $submit = replace_macros(get_markup_template('sellpage_submit.tpl'), array( '$continue' => t('Continue'), - '$address' => \App::$data['channel']['channel_address'] + '$address' => App::$data['channel']['channel_address'] )); $o = replace_macros(get_markup_template('sellpage_view.tpl'),array( @@ -120,7 +146,7 @@ class Connect extends \Zotlabs\Web\Controller { )); - $arr = array('channel' => \App::$data['channel'],'observer' => \App::get_observer(), 'sellpage' => $o, 'submit' => $submit); + $arr = array('channel' => App::$data['channel'],'observer' => App::get_observer(), 'sellpage' => $o, 'submit' => $submit); call_hooks('connect_premium', $arr); $o = $arr['sellpage']; diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index f35d6f147..1b96e4d14 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -111,7 +111,6 @@ class Settings_menu { ); } - if($role === false || $role === 'custom') { $tabs[] = array( 'label' => t('Connection Default Permissions'), @@ -120,22 +119,6 @@ class Settings_menu { ); } - if(feature_enabled(local_channel(),'premium_channel')) { - $tabs[] = array( - 'label' => t('Premium Channel Settings'), - 'url' => z_root() . '/connect/' . $channel['channel_address'], - 'selected' => '' - ); - } - - if(feature_enabled(local_channel(),'channel_sources')) { - $tabs[] = array( - 'label' => t('Channel Sources'), - 'url' => z_root() . '/sources', - 'selected' => '' - ); - } - $tabtpl = get_markup_template("generic_links_widget.tpl"); return replace_macros($tabtpl, array( '$title' => t('Settings'), @@ -144,4 +127,4 @@ class Settings_menu { )); } -} \ No newline at end of file +} -- cgit v1.2.3 From 39866b74637a58df5b1ffb8f2b6f164849d65315 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 25 Sep 2018 11:37:22 +0200 Subject: move start_menu switch to settings/display for now --- Zotlabs/Module/Settings/Display.php | 12 +++++++++++- Zotlabs/Widget/Newmember.php | 9 ++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php index 340b3c0bb..dbc383135 100644 --- a/Zotlabs/Module/Settings/Display.php +++ b/Zotlabs/Module/Settings/Display.php @@ -30,6 +30,7 @@ class Display { $channel_list_mode = ((x($_POST,'channel_list_mode')) ? intval($_POST['channel_list_mode']) : 0); $network_list_mode = ((x($_POST,'network_list_mode')) ? intval($_POST['network_list_mode']) : 0); $manual_update = ((array_key_exists('manual_update',$_POST)) ? intval($_POST['manual_update']) : 0); + $start_menu = ((x($_POST,'start_menu')) ? intval($_POST['start_menu']) : 0); $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400); if($channel_divmore_height < 50) @@ -60,6 +61,7 @@ class Display { set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height); set_pconfig(local_channel(),'system','manual_conversation_update', $manual_update); set_pconfig(local_channel(),'system','channel_menu', $channel_menu); + set_pconfig(local_channel(),'system','start_menu', $start_menu); $newschema = ''; if($theme){ @@ -150,6 +152,14 @@ class Display { $theme_selected = explode(':', $theme_selected)[0]; } + $account = \App::get_account(); + + if($account['account_created'] > datetime_convert('','','now - 60 days')) { + $start_menu = get_pconfig(local_channel(), 'system', 'start_menu', 1); + } + else { + $start_menu = get_pconfig(local_channel(), 'system', 'start_menu', 0); + } $preload_images = get_pconfig(local_channel(),'system','preload_images'); $preload_images = (($preload_images===false)? '0': $preload_images); // default if not set: 0 @@ -211,7 +221,7 @@ class Display { '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on grid page'), get_pconfig(local_channel(),'system','network_list_mode'), t('(comments displayed separately)'), $yes_no), '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')), '$network_divmore_height' => array('network_divmore_height', t('Grid page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')), - + '$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no] )); diff --git a/Zotlabs/Widget/Newmember.php b/Zotlabs/Widget/Newmember.php index 1a4b575b9..e57cf5171 100644 --- a/Zotlabs/Widget/Newmember.php +++ b/Zotlabs/Widget/Newmember.php @@ -17,7 +17,14 @@ class Newmember { if(! $a) return EMPTY_STR; - if(! feature_enabled(local_channel(),'start_menu')) + if($a['account_created'] > datetime_convert('','','now - 60 days')) { + $enabled = get_pconfig(local_channel(), 'system', 'start_menu', 1); + } + else { + $enabled = get_pconfig(local_channel(), 'system', 'start_menu', 0); + } + + if(! $enabled) return EMPTY_STR; $options = [ -- cgit v1.2.3 From 9bb0f1d18ece05ac1d37800c61d0b071f560dac3 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 25 Sep 2018 12:02:00 +0200 Subject: move advanced_theming switch to settings/display for now --- Zotlabs/Module/Settings/Display.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php index dbc383135..d35c54a90 100644 --- a/Zotlabs/Module/Settings/Display.php +++ b/Zotlabs/Module/Settings/Display.php @@ -30,7 +30,8 @@ class Display { $channel_list_mode = ((x($_POST,'channel_list_mode')) ? intval($_POST['channel_list_mode']) : 0); $network_list_mode = ((x($_POST,'network_list_mode')) ? intval($_POST['network_list_mode']) : 0); $manual_update = ((array_key_exists('manual_update',$_POST)) ? intval($_POST['manual_update']) : 0); - $start_menu = ((x($_POST,'start_menu')) ? intval($_POST['start_menu']) : 0); + $start_menu = ((x($_POST,'start_menu')) ? intval($_POST['start_menu']) : 0); + $advanced_theming = ((x($_POST,'advanced_theming')) ? intval($_POST['advanced_theming']) : 0); $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400); if($channel_divmore_height < 50) @@ -62,6 +63,7 @@ class Display { set_pconfig(local_channel(),'system','manual_conversation_update', $manual_update); set_pconfig(local_channel(),'system','channel_menu', $channel_menu); set_pconfig(local_channel(),'system','start_menu', $start_menu); + set_pconfig(local_channel(),'system','advanced_theming', $advanced_theming); $newschema = ''; if($theme){ @@ -179,6 +181,8 @@ class Display { $title_tosource = get_pconfig(local_channel(),'system','title_tosource'); $title_tosource = (($title_tosource===false)? '0': $title_tosource); // default if not set: 0 + $advanced_theming = get_pconfig(local_channel(),'system','advanced_theming', 0); + $theme_config = ""; if(($themeconfigfile = $this->get_theme_config_file($theme)) != null){ require_once($themeconfigfile); @@ -216,12 +220,13 @@ class Display { '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no), '$layout_editor' => t('System Page Layout Editor - (advanced)'), '$theme_config' => $theme_config, - '$expert' => feature_enabled(local_channel(),'advanced_theming'), + '$expert' => $advanced_theming, '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_channel(),'system','channel_list_mode'), t('(comments displayed separately)'), $yes_no), '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on grid page'), get_pconfig(local_channel(),'system','network_list_mode'), t('(comments displayed separately)'), $yes_no), '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')), '$network_divmore_height' => array('network_divmore_height', t('Grid page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')), - '$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no] + '$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no], + '$advanced_theming' => ['advanced_theming', t('Advanced Theme and Layout Settings'), $advanced_theming, t('Allows fine tuning of themes and page layouts'), $yes_no] )); -- cgit v1.2.3 From 9948bb3f2aa3bf3efa68623b87ba854fb59b4926 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 25 Sep 2018 12:59:53 +0200 Subject: appification of privacy groups --- Zotlabs/Module/Group.php | 29 ++++++++++++++++++++++++----- Zotlabs/Widget/Activity_filter.php | 4 +++- 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index acebe995d..bf0edb1ed 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -1,11 +1,13 @@ Privacy Groups App (Not Installed):
'; + $o .= t('Management of privacy groups'); + return $o; + } + // Switch to text mode interface if we have more than 'n' contacts or group members $switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit'); if($switchtotext === false) diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php index d725f8b55..912bfce49 100644 --- a/Zotlabs/Widget/Activity_filter.php +++ b/Zotlabs/Widget/Activity_filter.php @@ -2,6 +2,8 @@ namespace Zotlabs\Widget; +use Zotlabs\Lib\Apps; + class Activity_filter { function widget($arr) { @@ -44,7 +46,7 @@ class Activity_filter { ]; } - if(feature_enabled(local_channel(),'groups')) { + if(Apps::system_app_installed(local_channel(), 'Privacy Groups')) { $groups = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", intval(local_channel()) ); -- cgit v1.2.3 From 9bc76b425948e7a6118e7749a3eb7c08c447bab3 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 15:02:20 +0200 Subject: appification of the pdl editor and move advanced_theming to theme settings where it belongs --- Zotlabs/Module/Pdledit.php | 21 +++++++++++++++------ Zotlabs/Module/Settings/Display.php | 10 +--------- 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php index 9b86b599b..d0bde7715 100644 --- a/Zotlabs/Module/Pdledit.php +++ b/Zotlabs/Module/Pdledit.php @@ -1,15 +1,20 @@ PDL Editor App (Not Installed):
'; + $o .= t('Provides the ability to edit system page layouts'); + return $o; } if(argc() > 2 && argv(2) === 'reset') { diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php index d35c54a90..0c63a3056 100644 --- a/Zotlabs/Module/Settings/Display.php +++ b/Zotlabs/Module/Settings/Display.php @@ -31,7 +31,6 @@ class Display { $network_list_mode = ((x($_POST,'network_list_mode')) ? intval($_POST['network_list_mode']) : 0); $manual_update = ((array_key_exists('manual_update',$_POST)) ? intval($_POST['manual_update']) : 0); $start_menu = ((x($_POST,'start_menu')) ? intval($_POST['start_menu']) : 0); - $advanced_theming = ((x($_POST,'advanced_theming')) ? intval($_POST['advanced_theming']) : 0); $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400); if($channel_divmore_height < 50) @@ -63,7 +62,6 @@ class Display { set_pconfig(local_channel(),'system','manual_conversation_update', $manual_update); set_pconfig(local_channel(),'system','channel_menu', $channel_menu); set_pconfig(local_channel(),'system','start_menu', $start_menu); - set_pconfig(local_channel(),'system','advanced_theming', $advanced_theming); $newschema = ''; if($theme){ @@ -181,8 +179,6 @@ class Display { $title_tosource = get_pconfig(local_channel(),'system','title_tosource'); $title_tosource = (($title_tosource===false)? '0': $title_tosource); // default if not set: 0 - $advanced_theming = get_pconfig(local_channel(),'system','advanced_theming', 0); - $theme_config = ""; if(($themeconfigfile = $this->get_theme_config_file($theme)) != null){ require_once($themeconfigfile); @@ -218,16 +214,12 @@ class Display { '$channel_menu' => [ 'channel_menu', t('Provide channel menu in navigation bar'), get_pconfig(local_channel(),'system','channel_menu',get_config('system','channel_menu',0)), t('Default: channel menu located in app menu'),$yes_no ], '$manual_update' => array('manual_update', t('Manual conversation updates'), channel_manual_conv_update(local_channel()), t('Default is on, turning this off may increase screen jumping'), $yes_no), '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no), - '$layout_editor' => t('System Page Layout Editor - (advanced)'), '$theme_config' => $theme_config, - '$expert' => $advanced_theming, '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_channel(),'system','channel_list_mode'), t('(comments displayed separately)'), $yes_no), '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on grid page'), get_pconfig(local_channel(),'system','network_list_mode'), t('(comments displayed separately)'), $yes_no), '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')), '$network_divmore_height' => array('network_divmore_height', t('Grid page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')), - '$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no], - '$advanced_theming' => ['advanced_theming', t('Advanced Theme and Layout Settings'), $advanced_theming, t('Allows fine tuning of themes and page layouts'), $yes_no] - + '$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no] )); call_hooks('display_settings',$o); -- cgit v1.2.3 From aab97adb23c65dfc54f4f160742f8066fcd98032 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 16:22:34 +0200 Subject: oauth and oauth2 apps manager --- Zotlabs/Module/Oauth.php | 177 +++++++++++++++++++++++++++++++++ Zotlabs/Module/Oauth2.php | 199 +++++++++++++++++++++++++++++++++++++ Zotlabs/Module/Settings/Oauth.php | 161 ------------------------------ Zotlabs/Module/Settings/Oauth2.php | 184 ---------------------------------- 4 files changed, 376 insertions(+), 345 deletions(-) create mode 100644 Zotlabs/Module/Oauth.php create mode 100644 Zotlabs/Module/Oauth2.php delete mode 100644 Zotlabs/Module/Settings/Oauth.php delete mode 100644 Zotlabs/Module/Settings/Oauth2.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php new file mode 100644 index 000000000..196209308 --- /dev/null +++ b/Zotlabs/Module/Oauth.php @@ -0,0 +1,177 @@ + 1) && (argv(1) === 'edit' || argv(1) === 'add') && x($_POST,'submit')) { + + check_form_security_token_redirectOnErr('oauth', 'oauth'); + + $name = ((x($_POST,'name')) ? escape_tags($_POST['name']) : ''); + $key = ((x($_POST,'key')) ? escape_tags($_POST['key']) : ''); + $secret = ((x($_POST,'secret')) ? escape_tags($_POST['secret']) : ''); + $redirect = ((x($_POST,'redirect')) ? escape_tags($_POST['redirect']) : ''); + $icon = ((x($_POST,'icon')) ? escape_tags($_POST['icon']) : ''); + $oauth2 = ((x($_POST,'oauth2')) ? intval($_POST['oauth2']) : 0); + $ok = true; + if($name == '') { + $ok = false; + notice( t('Name is required') . EOL); + } + if($key == '' || $secret == '') { + $ok = false; + notice( t('Key and Secret are required') . EOL); + } + + if($ok) { + if ($_POST['submit']==t("Update")){ + $r = q("UPDATE clients SET + client_id='%s', + pw='%s', + clname='%s', + redirect_uri='%s', + icon='%s', + uid=%d + WHERE client_id='%s'", + dbesc($key), + dbesc($secret), + dbesc($name), + dbesc($redirect), + dbesc($icon), + intval(local_channel()), + dbesc($key)); + } else { + $r = q("INSERT INTO clients (client_id, pw, clname, redirect_uri, icon, uid) + VALUES ('%s','%s','%s','%s','%s',%d)", + dbesc($key), + dbesc($secret), + dbesc($name), + dbesc($redirect), + dbesc($icon), + intval(local_channel()) + ); + $r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ", + dbesc($key), + intval(local_channel()), + dbesc('all') + ); + } + } + goaway(z_root()."/oauth"); + return; + } + } + + function get() { + + if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'OAuth App (Not Installed):
'; + $o .= t('An OAuth apps manager'); + return $o; + } + + + if((argc() > 1) && (argv(1) === 'add')) { + $tpl = get_markup_template("oauth_edit.tpl"); + $o .= replace_macros($tpl, array( + '$form_security_token' => get_form_security_token("oauth"), + '$title' => t('Add application'), + '$submit' => t('Submit'), + '$cancel' => t('Cancel'), + '$name' => array('name', t('Name'), '', t('Name of application')), + '$key' => array('key', t('Consumer Key'), random_string(16), t('Automatically generated - change if desired. Max length 20')), + '$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')), + '$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')), + '$icon' => array('icon', t('Icon url'), '', t('Optional')), + )); + return $o; + } + + if((argc() > 2) && (argv(1) === 'edit')) { + $r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d", + dbesc(argv(2)), + local_channel()); + + if (!count($r)){ + notice(t('Application not found.')); + return; + } + $app = $r[0]; + + $tpl = get_markup_template("oauth_edit.tpl"); + $o .= replace_macros($tpl, array( + '$form_security_token' => get_form_security_token("oauth"), + '$title' => t('Add application'), + '$submit' => t('Update'), + '$cancel' => t('Cancel'), + '$name' => array('name', t('Name'), $app['clname'] , ''), + '$key' => array('key', t('Consumer Key'), $app['client_id'], ''), + '$secret' => array('secret', t('Consumer Secret'), $app['pw'], ''), + '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], ''), + '$icon' => array('icon', t('Icon url'), $app['icon'], ''), + )); + return $o; + } + + if((argc() > 2) && (argv(1) === 'delete')) { + check_form_security_token_redirectOnErr('/oauth', 'oauth', 't'); + + $r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d", + dbesc(argv(2)), + local_channel()); + goaway(z_root()."/oauth"); + return; + } + + + $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my + FROM clients + LEFT JOIN tokens ON clients.client_id=tokens.client_id + WHERE clients.uid IN (%d,0)", + local_channel(), + local_channel()); + + + $tpl = get_markup_template("oauth.tpl"); + $o .= replace_macros($tpl, array( + '$form_security_token' => get_form_security_token("oauth"), + '$baseurl' => z_root(), + '$title' => t('Connected OAuth Apps'), + '$add' => t('Add application'), + '$edit' => t('Edit'), + '$delete' => t('Delete'), + '$consumerkey' => t('Client key starts with'), + '$noname' => t('No name'), + '$remove' => t('Remove authorization'), + '$apps' => $r, + )); + return $o; + + } + +} diff --git a/Zotlabs/Module/Oauth2.php b/Zotlabs/Module/Oauth2.php new file mode 100644 index 000000000..2302d1b10 --- /dev/null +++ b/Zotlabs/Module/Oauth2.php @@ -0,0 +1,199 @@ + 1) && (argv(1) === 'edit' || argv(1) === 'add') && x($_POST,'submit')) { + + check_form_security_token_redirectOnErr('oauth2', 'oauth2'); + + $name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : ''); + $secret = ((x($_POST,'secret')) ? escape_tags(trim($_POST['secret'])) : ''); + $redirect = ((x($_POST,'redirect')) ? escape_tags(trim($_POST['redirect'])) : ''); + $grant = ((x($_POST,'grant')) ? escape_tags(trim($_POST['grant'])) : ''); + $scope = ((x($_POST,'scope')) ? escape_tags(trim($_POST['scope'])) : ''); + + $ok = true; + if($name == '' || $secret == '') { + $ok = false; + notice( t('Name and Secret are required') . EOL); + } + + if($ok) { + if ($_POST['submit']==t("Update")){ + $r = q("UPDATE oauth_clients SET + client_id = '%s', + client_secret = '%s', + redirect_uri = '%s', + grant_types = '%s', + scope = '%s', + user_id = %d + WHERE client_id='%s' and user_id = %s", + dbesc($name), + dbesc($secret), + dbesc($redirect), + dbesc($grant), + dbesc($scope), + intval(local_channel()), + dbesc($name), + intval(local_channel())); + } else { + $r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id) + VALUES ('%s','%s','%s','%s','%s',%d)", + dbesc($name), + dbesc($secret), + dbesc($redirect), + dbesc($grant), + dbesc($scope), + intval(local_channel()) + ); + $r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ", + dbesc($name), + intval(local_channel()), + dbesc('all') + ); + } + } + goaway(z_root()."/oauth2"); + return; + } + } + + function get() { + + if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'OAuth2 App (Not Installed):
'; + $o .= t('An OAuth2 apps manager'); + return $o; + } + + if((argc() > 1) && (argv(1) === 'add')) { + $tpl = get_markup_template("oauth2_edit.tpl"); + $o .= replace_macros($tpl, array( + '$form_security_token' => get_form_security_token("oauth2"), + '$title' => t('Add OAuth2 application'), + '$submit' => t('Submit'), + '$cancel' => t('Cancel'), + '$name' => array('name', t('Name'), '', t('Name of application')), + '$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')), + '$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')), + '$grant' => array('grant', t('Grant Types'), '', t('leave blank unless your application sepcifically requires this')), + '$scope' => array('scope', t('Authorization scope'), '', t('leave blank unless your application sepcifically requires this')), + )); + return $o; + } + + if((argc() > 2) && (argv(1) === 'edit')) { + $r = q("SELECT * FROM oauth_clients WHERE client_id='%s' AND user_id= %d", + dbesc(argv(2)), + intval(local_channel()) + ); + + if (! $r){ + notice(t('OAuth2 Application not found.')); + return; + } + + $app = $r[0]; + + $tpl = get_markup_template("oauth2_edit.tpl"); + $o .= replace_macros($tpl, array( + '$form_security_token' => get_form_security_token("oauth2"), + '$title' => t('Add application'), + '$submit' => t('Update'), + '$cancel' => t('Cancel'), + '$name' => array('name', t('Name'), $app['client_id'], t('Name of application')), + '$secret' => array('secret', t('Consumer Secret'), $app['client_secret'], t('Automatically generated - change if desired. Max length 20')), + '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], t('Redirect URI - leave blank unless your application specifically requires this')), + '$grant' => array('grant', t('Grant Types'), $app['grant_types'], t('leave blank unless your application specifically requires this')), + '$scope' => array('scope', t('Authorization scope'), $app['scope'], t('leave blank unless your application specifically requires this')), + )); + return $o; + } + + if((argc() > 2) && (argv(1) === 'delete')) { + check_form_security_token_redirectOnErr('oauth2', 'oauth2', 't'); + + $r = q("DELETE FROM oauth_clients WHERE client_id = '%s' AND user_id = %d", + dbesc(argv(2)), + intval(local_channel()) + ); + $r = q("DELETE FROM oauth_access_tokens WHERE client_id = '%s' AND user_id = %d", + dbesc(argv(2)), + intval(local_channel()) + ); + $r = q("DELETE FROM oauth_authorization_codes WHERE client_id = '%s' AND user_id = %d", + dbesc(argv(2)), + intval(local_channel()) + ); + $r = q("DELETE FROM oauth_refresh_tokens WHERE client_id = '%s' AND user_id = %d", + dbesc(argv(2)), + intval(local_channel()) + ); + goaway(z_root()."/oauth2"); + return; + } + + + $r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my + FROM oauth_clients + LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id AND + oauth_clients.user_id=oauth_access_tokens.user_id + WHERE oauth_clients.user_id IN (%d,0)", + intval(local_channel()), + intval(local_channel()) + ); + + $tpl = get_markup_template("oauth2.tpl"); + $o .= replace_macros($tpl, array( + '$form_security_token' => get_form_security_token("oauth2"), + '$baseurl' => z_root(), + '$title' => t('Connected OAuth2 Apps'), + '$add' => t('Add application'), + '$edit' => t('Edit'), + '$delete' => t('Delete'), + '$consumerkey' => t('Client key starts with'), + '$noname' => t('No name'), + '$remove' => t('Remove authorization'), + '$apps' => $r, + )); + return $o; + + } + +} diff --git a/Zotlabs/Module/Settings/Oauth.php b/Zotlabs/Module/Settings/Oauth.php deleted file mode 100644 index d6576c6de..000000000 --- a/Zotlabs/Module/Settings/Oauth.php +++ /dev/null @@ -1,161 +0,0 @@ - 2) && (argv(2) === 'edit' || argv(2) === 'add') && x($_POST,'submit')) { - - check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth'); - - $name = ((x($_POST,'name')) ? escape_tags($_POST['name']) : ''); - $key = ((x($_POST,'key')) ? escape_tags($_POST['key']) : ''); - $secret = ((x($_POST,'secret')) ? escape_tags($_POST['secret']) : ''); - $redirect = ((x($_POST,'redirect')) ? escape_tags($_POST['redirect']) : ''); - $icon = ((x($_POST,'icon')) ? escape_tags($_POST['icon']) : ''); - $oauth2 = ((x($_POST,'oauth2')) ? intval($_POST['oauth2']) : 0); - $ok = true; - if($name == '') { - $ok = false; - notice( t('Name is required') . EOL); - } - if($key == '' || $secret == '') { - $ok = false; - notice( t('Key and Secret are required') . EOL); - } - - if($ok) { - if ($_POST['submit']==t("Update")){ - $r = q("UPDATE clients SET - client_id='%s', - pw='%s', - clname='%s', - redirect_uri='%s', - icon='%s', - uid=%d - WHERE client_id='%s'", - dbesc($key), - dbesc($secret), - dbesc($name), - dbesc($redirect), - dbesc($icon), - intval(local_channel()), - dbesc($key)); - } else { - $r = q("INSERT INTO clients (client_id, pw, clname, redirect_uri, icon, uid) - VALUES ('%s','%s','%s','%s','%s',%d)", - dbesc($key), - dbesc($secret), - dbesc($name), - dbesc($redirect), - dbesc($icon), - intval(local_channel()) - ); - $r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ", - dbesc($key), - intval(local_channel()), - dbesc('all') - ); - } - } - goaway(z_root()."/settings/oauth/"); - return; - } - } - - function get() { - - if((argc() > 2) && (argv(2) === 'add')) { - $tpl = get_markup_template("settings_oauth_edit.tpl"); - $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("settings_oauth"), - '$title' => t('Add application'), - '$submit' => t('Submit'), - '$cancel' => t('Cancel'), - '$name' => array('name', t('Name'), '', t('Name of application')), - '$key' => array('key', t('Consumer Key'), random_string(16), t('Automatically generated - change if desired. Max length 20')), - '$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')), - '$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')), - '$icon' => array('icon', t('Icon url'), '', t('Optional')), - )); - return $o; - } - - if((argc() > 3) && (argv(2) === 'edit')) { - $r = q("SELECT * FROM clients WHERE client_id='%s' AND uid=%d", - dbesc(argv(3)), - local_channel()); - - if (!count($r)){ - notice(t('Application not found.')); - return; - } - $app = $r[0]; - - $tpl = get_markup_template("settings_oauth_edit.tpl"); - $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("settings_oauth"), - '$title' => t('Add application'), - '$submit' => t('Update'), - '$cancel' => t('Cancel'), - '$name' => array('name', t('Name'), $app['clname'] , ''), - '$key' => array('key', t('Consumer Key'), $app['client_id'], ''), - '$secret' => array('secret', t('Consumer Secret'), $app['pw'], ''), - '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], ''), - '$icon' => array('icon', t('Icon url'), $app['icon'], ''), - )); - return $o; - } - - if((argc() > 3) && (argv(2) === 'delete')) { - check_form_security_token_redirectOnErr('/settings/oauth', 'settings_oauth', 't'); - - $r = q("DELETE FROM clients WHERE client_id='%s' AND uid=%d", - dbesc(argv(3)), - local_channel()); - goaway(z_root()."/settings/oauth/"); - return; - } - - - $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my - FROM clients - LEFT JOIN tokens ON clients.client_id=tokens.client_id - WHERE clients.uid IN (%d,0)", - local_channel(), - local_channel()); - - - $tpl = get_markup_template("settings_oauth.tpl"); - $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("settings_oauth"), - '$baseurl' => z_root(), - '$title' => t('Connected Apps'), - '$add' => t('Add application'), - '$edit' => t('Edit'), - '$delete' => t('Delete'), - '$consumerkey' => t('Client key starts with'), - '$noname' => t('No name'), - '$remove' => t('Remove authorization'), - '$apps' => $r, - )); - return $o; - - } - -} \ No newline at end of file diff --git a/Zotlabs/Module/Settings/Oauth2.php b/Zotlabs/Module/Settings/Oauth2.php deleted file mode 100644 index 70fd3a5c3..000000000 --- a/Zotlabs/Module/Settings/Oauth2.php +++ /dev/null @@ -1,184 +0,0 @@ - 2) && (argv(2) === 'edit' || argv(2) === 'add') && x($_POST,'submit')) { - - check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2'); - - $name = ((x($_POST,'name')) ? escape_tags(trim($_POST['name'])) : ''); - $secret = ((x($_POST,'secret')) ? escape_tags(trim($_POST['secret'])) : ''); - $redirect = ((x($_POST,'redirect')) ? escape_tags(trim($_POST['redirect'])) : ''); - $grant = ((x($_POST,'grant')) ? escape_tags(trim($_POST['grant'])) : ''); - $scope = ((x($_POST,'scope')) ? escape_tags(trim($_POST['scope'])) : ''); - - $ok = true; - if($name == '' || $secret == '') { - $ok = false; - notice( t('Name and Secret are required') . EOL); - } - - if($ok) { - if ($_POST['submit']==t("Update")){ - $r = q("UPDATE oauth_clients SET - client_id = '%s', - client_secret = '%s', - redirect_uri = '%s', - grant_types = '%s', - scope = '%s', - user_id = %d - WHERE client_id='%s' and user_id = %s", - dbesc($name), - dbesc($secret), - dbesc($redirect), - dbesc($grant), - dbesc($scope), - intval(local_channel()), - dbesc($name), - intval(local_channel())); - } else { - $r = q("INSERT INTO oauth_clients (client_id, client_secret, redirect_uri, grant_types, scope, user_id) - VALUES ('%s','%s','%s','%s','%s',%d)", - dbesc($name), - dbesc($secret), - dbesc($redirect), - dbesc($grant), - dbesc($scope), - intval(local_channel()) - ); - $r = q("INSERT INTO xperm (xp_client, xp_channel, xp_perm) VALUES ('%s', %d, '%s') ", - dbesc($name), - intval(local_channel()), - dbesc('all') - ); - } - } - goaway(z_root()."/settings/oauth2/"); - return; - } - } - - function get() { - - if((argc() > 2) && (argv(2) === 'add')) { - $tpl = get_markup_template("settings_oauth2_edit.tpl"); - $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("settings_oauth2"), - '$title' => t('Add OAuth2 application'), - '$submit' => t('Submit'), - '$cancel' => t('Cancel'), - '$name' => array('name', t('Name'), '', t('Name of application')), - '$secret' => array('secret', t('Consumer Secret'), random_string(16), t('Automatically generated - change if desired. Max length 20')), - '$redirect' => array('redirect', t('Redirect'), '', t('Redirect URI - leave blank unless your application specifically requires this')), - '$grant' => array('grant', t('Grant Types'), '', t('leave blank unless your application sepcifically requires this')), - '$scope' => array('scope', t('Authorization scope'), '', t('leave blank unless your application sepcifically requires this')), - )); - return $o; - } - - if((argc() > 3) && (argv(2) === 'edit')) { - $r = q("SELECT * FROM oauth_clients WHERE client_id='%s' AND user_id= %d", - dbesc(argv(3)), - intval(local_channel()) - ); - - if (! $r){ - notice(t('OAuth2 Application not found.')); - return; - } - - $app = $r[0]; - - $tpl = get_markup_template("settings_oauth2_edit.tpl"); - $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("settings_oauth2"), - '$title' => t('Add application'), - '$submit' => t('Update'), - '$cancel' => t('Cancel'), - '$name' => array('name', t('Name'), $app['client_id'], t('Name of application')), - '$secret' => array('secret', t('Consumer Secret'), $app['client_secret'], t('Automatically generated - change if desired. Max length 20')), - '$redirect' => array('redirect', t('Redirect'), $app['redirect_uri'], t('Redirect URI - leave blank unless your application specifically requires this')), - '$grant' => array('grant', t('Grant Types'), $app['grant_types'], t('leave blank unless your application specifically requires this')), - '$scope' => array('scope', t('Authorization scope'), $app['scope'], t('leave blank unless your application specifically requires this')), - )); - return $o; - } - - if((argc() > 3) && (argv(2) === 'delete')) { - check_form_security_token_redirectOnErr('/settings/oauth2', 'settings_oauth2', 't'); - - $r = q("DELETE FROM oauth_clients WHERE client_id = '%s' AND user_id = %d", - dbesc(argv(3)), - intval(local_channel()) - ); - $r = q("DELETE FROM oauth_access_tokens WHERE client_id = '%s' AND user_id = %d", - dbesc(argv(3)), - intval(local_channel()) - ); - $r = q("DELETE FROM oauth_authorization_codes WHERE client_id = '%s' AND user_id = %d", - dbesc(argv(3)), - intval(local_channel()) - ); - $r = q("DELETE FROM oauth_refresh_tokens WHERE client_id = '%s' AND user_id = %d", - dbesc(argv(3)), - intval(local_channel()) - ); - goaway(z_root()."/settings/oauth2/"); - return; - } - - - $r = q("SELECT oauth_clients.*, oauth_access_tokens.access_token as oauth_token, (oauth_clients.user_id = %d) AS my - FROM oauth_clients - LEFT JOIN oauth_access_tokens ON oauth_clients.client_id=oauth_access_tokens.client_id AND - oauth_clients.user_id=oauth_access_tokens.user_id - WHERE oauth_clients.user_id IN (%d,0)", - intval(local_channel()), - intval(local_channel()) - ); - - $tpl = get_markup_template("settings_oauth2.tpl"); - $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("settings_oauth2"), - '$baseurl' => z_root(), - '$title' => t('Connected OAuth2 Apps'), - '$add' => t('Add application'), - '$edit' => t('Edit'), - '$delete' => t('Delete'), - '$consumerkey' => t('Client key starts with'), - '$noname' => t('No name'), - '$remove' => t('Remove authorization'), - '$apps' => $r, - )); - return $o; - - } - -} -- cgit v1.2.3 From d7ec36e3da017bff3bed64d2714e9cdf460e0c18 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 16:23:12 +0200 Subject: wrong app name --- Zotlabs/Module/Oauth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php index 196209308..9297eb65d 100644 --- a/Zotlabs/Module/Oauth.php +++ b/Zotlabs/Module/Oauth.php @@ -11,7 +11,7 @@ class Oauth extends Controller { function post() { - if(! Apps::system_app_installed(local_channel(), 'OAuth')) + if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager')) return; if(x($_POST,'remove')){ -- cgit v1.2.3 From 9af1b62beef76781e3384a536377d9f8123aab07 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 16:26:36 +0200 Subject: change wording --- Zotlabs/Module/Oauth.php | 4 ++-- Zotlabs/Module/Oauth2.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php index 9297eb65d..d087ecec4 100644 --- a/Zotlabs/Module/Oauth.php +++ b/Zotlabs/Module/Oauth.php @@ -90,8 +90,8 @@ class Oauth extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'OAuth App (Not Installed):
'; - $o .= t('An OAuth apps manager'); + $o = 'OAuth Apps Manager App (Not Installed):
'; + $o .= t('OAuth authenticatication tokens for mobile and remote apps'); return $o; } diff --git a/Zotlabs/Module/Oauth2.php b/Zotlabs/Module/Oauth2.php index 2302d1b10..4c34b499f 100644 --- a/Zotlabs/Module/Oauth2.php +++ b/Zotlabs/Module/Oauth2.php @@ -97,8 +97,8 @@ class Oauth2 extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'OAuth2 App (Not Installed):
'; - $o .= t('An OAuth2 apps manager'); + $o = 'OAuth2 Apps Manager App (Not Installed):
'; + $o .= t('OAuth2 authenticatication tokens for mobile and remote apps'); return $o; } -- cgit v1.2.3 From 1353c291e9d6fbe4cdbe8e4911f99d51e1da9198 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 16:32:06 +0200 Subject: add check for local_channel() --- Zotlabs/Module/Oauth.php | 7 +++++++ Zotlabs/Module/Oauth2.php | 6 ++++++ 2 files changed, 13 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php index d087ecec4..5aae71ae7 100644 --- a/Zotlabs/Module/Oauth.php +++ b/Zotlabs/Module/Oauth.php @@ -11,6 +11,10 @@ class Oauth extends Controller { function post() { + if(! local_channel()) + return; + + if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager')) return; @@ -86,6 +90,9 @@ class Oauth extends Controller { function get() { + if(! local_channel()) + return; + if(! Apps::system_app_installed(local_channel(), 'OAuth Apps Manager')) { //Do not display any associated widgets at this point App::$pdl = ''; diff --git a/Zotlabs/Module/Oauth2.php b/Zotlabs/Module/Oauth2.php index 4c34b499f..c27d7534b 100644 --- a/Zotlabs/Module/Oauth2.php +++ b/Zotlabs/Module/Oauth2.php @@ -11,6 +11,9 @@ class Oauth2 extends Controller { function post() { + if(! local_channel()) + return; + if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager')) return; @@ -93,6 +96,9 @@ class Oauth2 extends Controller { function get() { + if(! local_channel()) + return; + if(! Apps::system_app_installed(local_channel(), 'OAuth2 Apps Manager')) { //Do not display any associated widgets at this point App::$pdl = ''; -- cgit v1.2.3 From 505782f224d232acd57f7a5986adfc9bf8a7bb79 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 16:35:05 +0200 Subject: remove oauth from features --- Zotlabs/Widget/Settings_menu.php | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index 1b96e4d14..041ca312f 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -79,22 +79,6 @@ class Settings_menu { 'selected' => '' ); - if(feature_enabled(local_channel(),'oauth_clients')) { - $tabs[] = array( - 'label' => t('OAuth1 apps'), - 'url' => z_root() . '/settings/oauth', - 'selected' => ((argv(1) === 'oauth') ? 'active' : ''), - ); - } - - if(feature_enabled(local_channel(),'oauth2_clients')) { - $tabs[] = array( - 'label' => t('OAuth2 apps'), - 'url' => z_root() . '/settings/oauth2', - 'selected' => ((argv(1) === 'oauth2') ? 'active' : ''), - ); - } - if(feature_enabled(local_channel(),'access_tokens')) { $tabs[] = array( 'label' => t('Guest Access Tokens'), -- cgit v1.2.3 From a7948d7bfee1c0c8c9f1a731aabdc636c280bff0 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 22:02:50 +0200 Subject: permcats app --- Zotlabs/Module/Connedit.php | 3 +- Zotlabs/Module/Defperms.php | 3 +- Zotlabs/Module/Permcats.php | 135 +++++++++++++++++++++++++++++++++++ Zotlabs/Module/Settings/Permcats.php | 120 ------------------------------- Zotlabs/Widget/Settings_menu.php | 8 --- 5 files changed, 139 insertions(+), 130 deletions(-) create mode 100644 Zotlabs/Module/Permcats.php delete mode 100644 Zotlabs/Module/Settings/Permcats.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index 712215bc3..3d7ee449a 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -7,6 +7,7 @@ namespace Zotlabs\Module; * */ +use Zotlabs\Lib\Apps; require_once('include/socgraph.php'); require_once('include/selectors.php'); @@ -851,7 +852,7 @@ class Connedit extends \Zotlabs\Web\Controller { '$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no), '$permcat' => [ 'permcat', t('Permission role'), '', '',$permcats ], '$permcat_new' => t('Add permission role'), - '$permcat_enable' => feature_enabled(local_channel(),'permcats'), + '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'), '$addr' => unpunify($contact['xchan_addr']), '$primeurl' => unpunify($contact['xchan_url']), '$section' => $section, diff --git a/Zotlabs/Module/Defperms.php b/Zotlabs/Module/Defperms.php index 63acc9795..2e886aa64 100644 --- a/Zotlabs/Module/Defperms.php +++ b/Zotlabs/Module/Defperms.php @@ -1,6 +1,7 @@ array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no), '$permcat' => [ 'permcat', t('Permission role'), '', '',$permcats ], '$permcat_new' => t('Add permission role'), - '$permcat_enable' => feature_enabled(local_channel(),'permcats'), + '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'), '$section' => $section, '$sections' => $sections, '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'), diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php new file mode 100644 index 000000000..97090067b --- /dev/null +++ b/Zotlabs/Module/Permcats.php @@ -0,0 +1,135 @@ + $desc) { + if(array_key_exists('perms_' . $perm, $_POST)) { + $pcarr[] = $perm; + } + } + } + + \Zotlabs\Lib\Permcat::update(local_channel(),$name,$pcarr); + + build_sync_packet(); + + info( t('Permission category saved.') . EOL); + + return; + } + + + function get() { + + if(! local_channel()) + return; + + if(! Apps::system_app_installed(local_channel(), 'Permission Categories')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'Permission Categories App (Not Installed):
'; + $o .= t('Create custom connection permission limits'); + return $o; + } + + $channel = App::get_channel(); + + + if(argc() > 1) + $name = hex2bin(argv(1)); + + if(argc() > 2 && argv(2) === 'drop') { + \Zotlabs\Lib\Permcat::delete(local_channel(),$name); + build_sync_packet(); + json_return_and_die([ 'success' => true ]); + } + + + $desc = t('Use this form to create permission rules for various classes of people or connections.'); + + $existing = []; + + $pcat = new \Zotlabs\Lib\Permcat(local_channel()); + $pcatlist = $pcat->listing(); + $permcats = []; + if($pcatlist) { + foreach($pcatlist as $pc) { + if(($pc['name']) && ($name) && ($pc['name'] == $name)) + $existing = $pc['perms']; + if(! $pc['system']) + $permcats[bin2hex($pc['name'])] = $pc['localname']; + } + } + + $global_perms = \Zotlabs\Access\Permissions::Perms(); + + foreach($global_perms as $k => $v) { + $thisperm = \Zotlabs\Lib\Permcat::find_permcat($existing,$k); + $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k); + + if($existing[$k]) + $thisperm = "1"; + + $perms[] = array('perms_' . $k, $v, '',$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited); + } + + + + $tpl = get_markup_template("permcats.tpl"); + $o .= replace_macros($tpl, array( + '$form_security_token' => get_form_security_token("permcats"), + '$title' => t('Permission Categories'), + '$desc' => $desc, + '$desc2' => $desc2, + '$tokens' => $t, + '$permcats' => $permcats, + '$atoken' => $atoken, + '$url1' => z_root() . '/channel/' . $channel['channel_address'], + '$url2' => z_root() . '/photos/' . $channel['channel_address'], + '$name' => array('name', t('Permission Name') . ' *', (($name) ? $name : ''), ''), + '$me' => t('My Settings'), + '$perms' => $perms, + '$inherited' => t('inherited'), + '$notself' => 0, + '$self' => 1, + '$permlbl' => t('Individual Permissions'), + '$permnote' => t('Some permissions may be inherited from your channel\'s privacy settings, which have higher priority than individual settings. You can not change those settings here.'), + '$submit' => t('Submit') + )); + return $o; + } + +} diff --git a/Zotlabs/Module/Settings/Permcats.php b/Zotlabs/Module/Settings/Permcats.php deleted file mode 100644 index 40641c3f2..000000000 --- a/Zotlabs/Module/Settings/Permcats.php +++ /dev/null @@ -1,120 +0,0 @@ - $desc) { - if(array_key_exists('perms_' . $perm, $_POST)) { - $pcarr[] = $perm; - } - } - } - - \Zotlabs\Lib\Permcat::update(local_channel(),$name,$pcarr); - - build_sync_packet(); - - info( t('Permission category saved.') . EOL); - - return; - } - - - function get() { - - if(! local_channel()) - return; - - $channel = \App::get_channel(); - - - if(argc() > 2) - $name = hex2bin(argv(2)); - - if(argc() > 3 && argv(3) === 'drop') { - \Zotlabs\Lib\Permcat::delete(local_channel(),$name); - build_sync_packet(); - json_return_and_die([ 'success' => true ]); - } - - - $desc = t('Use this form to create permission rules for various classes of people or connections.'); - - $existing = []; - - $pcat = new \Zotlabs\Lib\Permcat(local_channel()); - $pcatlist = $pcat->listing(); - $permcats = []; - if($pcatlist) { - foreach($pcatlist as $pc) { - if(($pc['name']) && ($name) && ($pc['name'] == $name)) - $existing = $pc['perms']; - if(! $pc['system']) - $permcats[bin2hex($pc['name'])] = $pc['localname']; - } - } - - $global_perms = \Zotlabs\Access\Permissions::Perms(); - - foreach($global_perms as $k => $v) { - $thisperm = \Zotlabs\Lib\Permcat::find_permcat($existing,$k); - $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k); - - if($existing[$k]) - $thisperm = "1"; - - $perms[] = array('perms_' . $k, $v, '',$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited); - } - - - - $tpl = get_markup_template("settings_permcats.tpl"); - $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("settings_permcats"), - '$title' => t('Permission Categories'), - '$desc' => $desc, - '$desc2' => $desc2, - '$tokens' => $t, - '$permcats' => $permcats, - '$atoken' => $atoken, - '$url1' => z_root() . '/channel/' . $channel['channel_address'], - '$url2' => z_root() . '/photos/' . $channel['channel_address'], - '$name' => array('name', t('Permission Name') . ' *', (($name) ? $name : ''), ''), - '$me' => t('My Settings'), - '$perms' => $perms, - '$inherited' => t('inherited'), - '$notself' => 0, - '$self' => 1, - '$permlbl' => t('Individual Permissions'), - '$permnote' => t('Some permissions may be inherited from your channel\'s privacy settings, which have higher priority than individual settings. You can not change those settings here.'), - '$submit' => t('Submit') - )); - return $o; - } - -} diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index 041ca312f..781f3b145 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -87,14 +87,6 @@ class Settings_menu { ); } - if(feature_enabled(local_channel(),'permcats')) { - $tabs[] = array( - 'label' => t('Permission Categories'), - 'url' => z_root() . '/settings/permcats', - 'selected' => ((argv(1) === 'permcats') ? 'active' : ''), - ); - } - if($role === false || $role === 'custom') { $tabs[] = array( 'label' => t('Connection Default Permissions'), -- cgit v1.2.3 From e3c04b1fd0f441e0042e218f47696b1bfad26c73 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 22:24:36 +0200 Subject: guest access app --- Zotlabs/Module/Permcats.php | 4 +- Zotlabs/Module/Settings/Tokens.php | 173 --------------------------------- Zotlabs/Module/Tokens.php | 193 +++++++++++++++++++++++++++++++++++++ Zotlabs/Widget/Settings_menu.php | 8 -- 4 files changed, 194 insertions(+), 184 deletions(-) delete mode 100644 Zotlabs/Module/Settings/Tokens.php create mode 100644 Zotlabs/Module/Tokens.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php index 97090067b..3d068862a 100644 --- a/Zotlabs/Module/Permcats.php +++ b/Zotlabs/Module/Permcats.php @@ -14,8 +14,7 @@ class Permcats extends Controller { return; if(! Apps::system_app_installed(local_channel(), 'Permission Categories')) - return - + return; $channel = App::get_channel(); @@ -67,7 +66,6 @@ class Permcats extends Controller { $channel = App::get_channel(); - if(argc() > 1) $name = hex2bin(argv(1)); diff --git a/Zotlabs/Module/Settings/Tokens.php b/Zotlabs/Module/Settings/Tokens.php deleted file mode 100644 index e59cf8d1c..000000000 --- a/Zotlabs/Module/Settings/Tokens.php +++ /dev/null @@ -1,173 +0,0 @@ -= $max_tokens) { - notice( sprintf( t('This channel is limited to %d tokens'), $max_tokens) . EOL); - return; - } - } - } - if($token_errs) { - notice( t('Name and Password are required.') . EOL); - return; - } - if($atoken_id) { - $r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s' - where atoken_id = %d and atoken_uid = %d", - dbesc($name), - dbesc($token), - dbesc($expires), - intval($atoken_id), - intval($channel['channel_id']) - ); - } - else { - $r = q("insert into atoken ( atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires ) - values ( %d, %d, '%s', '%s', '%s' ) ", - intval($channel['channel_account_id']), - intval($channel['channel_id']), - dbesc($name), - dbesc($token), - dbesc($expires) - ); - } - - $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $name; - - $all_perms = \Zotlabs\Access\Permissions::Perms(); - - if($all_perms) { - foreach($all_perms as $perm => $desc) { - if(array_key_exists('perms_' . $perm, $_POST)) { - set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,intval($_POST['perms_' . $perm])); - } - else { - set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,0); - } - } - } - - - info( t('Token saved.') . EOL); - return; - } - - - function get() { - - $channel = \App::get_channel(); - - $atoken = null; - $atoken_xchan = ''; - - if(argc() > 2) { - $id = argv(2); - - $atoken = q("select * from atoken where atoken_id = %d and atoken_uid = %d", - intval($id), - intval(local_channel()) - ); - - if($atoken) { - $atoken = $atoken[0]; - $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_name']; - } - - if($atoken && argc() > 3 && argv(3) === 'drop') { - atoken_delete($id); - $atoken = null; - $atoken_xchan = ''; - } - } - - $t = q("select * from atoken where atoken_uid = %d", - intval(local_channel()) - ); - - $desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content.'); - - $desc2 = t('You may also provide dropbox style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:'); - - $global_perms = \Zotlabs\Access\Permissions::Perms(); - $their_perms = []; - - $existing = get_all_perms(local_channel(),(($atoken_xchan) ? $atoken_xchan : ''),false); - - if($atoken_xchan) { - $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", - intval(local_channel()), - dbesc($atoken_xchan) - ); - if($theirs) { - foreach($theirs as $t) { - $their_perms[$t['k']] = $t['v']; - } - } - } - foreach($global_perms as $k => $v) { - $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k); -//fixme - - $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k); - - if($existing[$k]) - $thisperm = "1"; - - $perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited); - } - - - - $tpl = get_markup_template("settings_tokens.tpl"); - $o .= replace_macros($tpl, array( - '$form_security_token' => get_form_security_token("settings_tokens"), - '$title' => t('Guest Access Tokens'), - '$desc' => $desc, - '$desc2' => $desc2, - '$tokens' => $t, - '$atoken' => $atoken, - '$url1' => z_root() . '/channel/' . $channel['channel_address'], - '$url2' => z_root() . '/photos/' . $channel['channel_address'], - '$name' => array('name', t('Login Name') . ' *', (($atoken) ? $atoken['atoken_name'] : ''),''), - '$token'=> array('token', t('Login Password') . ' *',(($atoken) ? $atoken['atoken_token'] : autoname(8)), ''), - '$expires'=> array('expires', t('Expires (yyyy-mm-dd)'), (($atoken['atoken_expires'] && $atoken['atoken_expires'] > NULL_DATE) ? datetime_convert('UTC',date_default_timezone_get(),$atoken['atoken_expires']) : ''), ''), - '$them' => t('Their Settings'), - '$me' => t('My Settings'), - '$perms' => $perms, - '$inherited' => t('inherited'), - '$notself' => 1, - '$self' => 0, - '$permlbl' => t('Individual Permissions'), - '$permnote' => t('Some permissions may be inherited from your channel\'s privacy settings, which have higher priority than individual settings. You can not change those settings here.'), - '$submit' => t('Submit') - )); - return $o; - } - -} diff --git a/Zotlabs/Module/Tokens.php b/Zotlabs/Module/Tokens.php new file mode 100644 index 000000000..a791d3f63 --- /dev/null +++ b/Zotlabs/Module/Tokens.php @@ -0,0 +1,193 @@ += $max_tokens) { + notice( sprintf( t('This channel is limited to %d tokens'), $max_tokens) . EOL); + return; + } + } + } + if($token_errs) { + notice( t('Name and Password are required.') . EOL); + return; + } + if($atoken_id) { + $r = q("update atoken set atoken_name = '%s', atoken_token = '%s', atoken_expires = '%s' + where atoken_id = %d and atoken_uid = %d", + dbesc($name), + dbesc($token), + dbesc($expires), + intval($atoken_id), + intval($channel['channel_id']) + ); + } + else { + $r = q("insert into atoken ( atoken_aid, atoken_uid, atoken_name, atoken_token, atoken_expires ) + values ( %d, %d, '%s', '%s', '%s' ) ", + intval($channel['channel_account_id']), + intval($channel['channel_id']), + dbesc($name), + dbesc($token), + dbesc($expires) + ); + } + + $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $name; + + $all_perms = \Zotlabs\Access\Permissions::Perms(); + + if($all_perms) { + foreach($all_perms as $perm => $desc) { + if(array_key_exists('perms_' . $perm, $_POST)) { + set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,intval($_POST['perms_' . $perm])); + } + else { + set_abconfig($channel['channel_id'],$atoken_xchan,'my_perms',$perm,0); + } + } + } + + + info( t('Token saved.') . EOL); + return; + } + + + function get() { + + if(! local_channel()) + return; + + if(! Apps::system_app_installed(local_channel(), 'Guest Access')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = 'Guest Access App (Not Installed):
'; + $o .= t('Create access tokens so that non-members can access private content'); + return $o; + } + + $channel = App::get_channel(); + + $atoken = null; + $atoken_xchan = ''; + + if(argc() > 2) { + $id = argv(2); + + $atoken = q("select * from atoken where atoken_id = %d and atoken_uid = %d", + intval($id), + intval(local_channel()) + ); + + if($atoken) { + $atoken = $atoken[0]; + $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_name']; + } + + if($atoken && argc() > 3 && argv(3) === 'drop') { + atoken_delete($id); + $atoken = null; + $atoken_xchan = ''; + } + } + + $t = q("select * from atoken where atoken_uid = %d", + intval(local_channel()) + ); + + $desc = t('Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content.'); + + $desc2 = t('You may also provide dropbox style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:'); + + $global_perms = \Zotlabs\Access\Permissions::Perms(); + $their_perms = []; + + $existing = get_all_perms(local_channel(),(($atoken_xchan) ? $atoken_xchan : ''),false); + + if($atoken_xchan) { + $theirs = q("select * from abconfig where chan = %d and xchan = '%s' and cat = 'their_perms'", + intval(local_channel()), + dbesc($atoken_xchan) + ); + if($theirs) { + foreach($theirs as $t) { + $their_perms[$t['k']] = $t['v']; + } + } + } + foreach($global_perms as $k => $v) { + $thisperm = get_abconfig(local_channel(),$contact['abook_xchan'],'my_perms',$k); +//fixme + + $checkinherited = \Zotlabs\Access\PermissionLimits::Get(local_channel(),$k); + + if($existing[$k]) + $thisperm = "1"; + + $perms[] = array('perms_' . $k, $v, ((array_key_exists($k,$their_perms)) ? intval($their_perms[$k]) : ''),$thisperm, 1, (($checkinherited & PERMS_SPECIFIC) ? '' : '1'), '', $checkinherited); + } + + + + $tpl = get_markup_template("tokens.tpl"); + $o .= replace_macros($tpl, array( + '$form_security_token' => get_form_security_token("tokens"), + '$title' => t('Guest Access Tokens'), + '$desc' => $desc, + '$desc2' => $desc2, + '$tokens' => $t, + '$atoken' => $atoken, + '$url1' => z_root() . '/channel/' . $channel['channel_address'], + '$url2' => z_root() . '/photos/' . $channel['channel_address'], + '$name' => array('name', t('Login Name') . ' *', (($atoken) ? $atoken['atoken_name'] : ''),''), + '$token'=> array('token', t('Login Password') . ' *',(($atoken) ? $atoken['atoken_token'] : autoname(8)), ''), + '$expires'=> array('expires', t('Expires (yyyy-mm-dd)'), (($atoken['atoken_expires'] && $atoken['atoken_expires'] > NULL_DATE) ? datetime_convert('UTC',date_default_timezone_get(),$atoken['atoken_expires']) : ''), ''), + '$them' => t('Their Settings'), + '$me' => t('My Settings'), + '$perms' => $perms, + '$inherited' => t('inherited'), + '$notself' => 1, + '$self' => 0, + '$permlbl' => t('Individual Permissions'), + '$permnote' => t('Some permissions may be inherited from your channel\'s privacy settings, which have higher priority than individual settings. You can not change those settings here.'), + '$submit' => t('Submit') + )); + return $o; + } + +} diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index 781f3b145..ecf93ec78 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -79,14 +79,6 @@ class Settings_menu { 'selected' => '' ); - if(feature_enabled(local_channel(),'access_tokens')) { - $tabs[] = array( - 'label' => t('Guest Access Tokens'), - 'url' => z_root() . '/settings/tokens', - 'selected' => ((argv(1) === 'tokens') ? 'active' : ''), - ); - } - if($role === false || $role === 'custom') { $tabs[] = array( 'label' => t('Connection Default Permissions'), -- cgit v1.2.3 From bdf6289b323c26329087eb21911576239e0b6216 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 26 Sep 2018 22:32:06 +0200 Subject: tokens: add css file and fix argc and argv values --- Zotlabs/Module/Tokens.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Tokens.php b/Zotlabs/Module/Tokens.php index a791d3f63..ae03a499a 100644 --- a/Zotlabs/Module/Tokens.php +++ b/Zotlabs/Module/Tokens.php @@ -106,8 +106,8 @@ class Tokens extends Controller { $atoken = null; $atoken_xchan = ''; - if(argc() > 2) { - $id = argv(2); + if(argc() > 1) { + $id = argv(1); $atoken = q("select * from atoken where atoken_id = %d and atoken_uid = %d", intval($id), @@ -119,7 +119,7 @@ class Tokens extends Controller { $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_name']; } - if($atoken && argc() > 3 && argv(3) === 'drop') { + if($atoken && argc() > 2 && argv(2) === 'drop') { atoken_delete($id); $atoken = null; $atoken_xchan = ''; -- cgit v1.2.3 From 6b23c3e1796b818ce893ed919f2e2bdd000c83fb Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 27 Sep 2018 14:56:47 +0200 Subject: implement conversation tools (settings/conversation), remove additional features from the settings menu and get rid of skill levels --- Zotlabs/Lib/ThreadItem.php | 7 ++-- Zotlabs/Module/Settings/Conversation.php | 60 ++++++++++++++++++++++++++++++++ Zotlabs/Module/Settings/Features.php | 35 +------------------ Zotlabs/Widget/Settings_menu.php | 8 ----- 4 files changed, 66 insertions(+), 44 deletions(-) create mode 100644 Zotlabs/Module/Settings/Conversation.php (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index f8a7366f8..ac24806a6 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -259,7 +259,7 @@ class ThreadItem { $forged = ((($item['sig']) && (! intval($item['item_verified']))) ? t('Message signature incorrect') : ''); $unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : ''); - + $settings = ''; // FIXME - check this permission if($conv->get_profile_owner() == local_channel()) { @@ -267,6 +267,8 @@ class ThreadItem { 'tagit' => t("Add Tag"), 'classtagger' => "", ); + + $settings = t('Conversation Tools'); } $has_bookmarks = false; @@ -436,7 +438,8 @@ class ThreadItem { 'preview_lbl' => t('This is an unsaved preview'), 'wait' => t('Please wait'), 'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])), - 'thread_level' => $thread_level + 'thread_level' => $thread_level, + 'settings' => $settings ); $arr = array('item' => $item, 'output' => $tmp_item); diff --git a/Zotlabs/Module/Settings/Conversation.php b/Zotlabs/Module/Settings/Conversation.php new file mode 100644 index 000000000..43e59a3c2 --- /dev/null +++ b/Zotlabs/Module/Settings/Conversation.php @@ -0,0 +1,60 @@ + 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), + '$title' => t('Conversation Settings'), + '$features' => process_module_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + if($aj) { + echo $o; + killme(); + } + else { + return $o; + } + } + +} diff --git a/Zotlabs/Module/Settings/Features.php b/Zotlabs/Module/Settings/Features.php index 888032c28..6a3ab104b 100644 --- a/Zotlabs/Module/Settings/Features.php +++ b/Zotlabs/Module/Settings/Features.php @@ -26,44 +26,14 @@ class Features { function get() { $arr = []; - $harr = []; - if(intval($_REQUEST['techlevel'])) - $level = intval($_REQUEST['techlevel']); - else { - $level = get_account_techlevel(); - } - - if(! intval($level)) { - notice( t('Permission denied.') . EOL); - return; - } - - $techlevels = \Zotlabs\Lib\Techlevels::levels(); - - // This page isn't accessible at techlevel 0 - - unset($techlevels[0]); - - $def_techlevel = (($level > 0) ? $level : 1); - $techlock = get_config('system','techlevel_lock'); - - $all_features_raw = get_features(false); - - foreach($all_features_raw as $fname => $fdata) { - foreach(array_slice($fdata,1) as $f) { - $harr[$f[0]] = ((intval(feature_enabled(local_channel(),$f[0]))) ? "1" : ''); - } - } - - $features = get_features(true,$level); + $features = get_features(false); foreach($features as $fname => $fdata) { $arr[$fname] = array(); $arr[$fname][0] = $fdata[0]; foreach(array_slice($fdata,1) as $f) { $arr[$fname][1][] = array('feature_' . $f[0],$f[1],((intval(feature_enabled(local_channel(),$f[0]))) ? "1" : ''),$f[2],array(t('Off'),t('On'))); - unset($harr[$f[0]]); } } @@ -71,10 +41,7 @@ class Features { $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("settings_features"), '$title' => t('Additional Features'), - '$techlevel' => [ 'techlevel', t('Your technical skill level'), $def_techlevel, t('Used to provide a member experience and additional features consistent with your comfort level'), $techlevels ], - '$techlock' => $techlock, '$features' => $arr, - '$hiddens' => $harr, '$baseurl' => z_root(), '$submit' => t('Submit'), )); diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index ecf93ec78..92f615452 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -45,14 +45,6 @@ class Settings_menu { ); - if(get_account_techlevel() > 0 && get_features()) { - $tabs[] = array( - 'label' => t('Additional features'), - 'url' => z_root().'/settings/features', - 'selected' => ((argv(1) === 'features') ? 'active' : ''), - ); - } - $tabs[] = array( 'label' => t('Addon settings'), 'url' => z_root().'/settings/featured', -- cgit v1.2.3 From 6f98ca68af59e7c27179b5b9712a4fa015ad7f47 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Thu, 27 Sep 2018 13:37:15 -0400 Subject: Translate system app names --- Zotlabs/Lib/Apps.php | 1 + 1 file changed, 1 insertion(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 4ee64f15e..519d5f35a 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -763,6 +763,7 @@ class Apps { call_hooks('app_list',$hookinfo); $r = $hookinfo['apps']; for($x = 0; $x < count($r); $x ++) { + $r[$x]['app_name']=t(trim($r[$x]['app_name'])); if(! $r[$x]['app_system']) $r[$x]['type'] = 'personal'; $r[$x]['term'] = q("select * from term where otype = %d and oid = %d", -- cgit v1.2.3 From 56fdc4f3febbc5a2242d8ce6ab6d51f83feae42d Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Thu, 27 Sep 2018 20:26:47 +0200 Subject: Missprint in Oauth.php fixed --- Zotlabs/Module/Oauth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php index 5aae71ae7..fbcc48ead 100644 --- a/Zotlabs/Module/Oauth.php +++ b/Zotlabs/Module/Oauth.php @@ -98,7 +98,7 @@ class Oauth extends Controller { App::$pdl = ''; $o = 'OAuth Apps Manager App (Not Installed):
'; - $o .= t('OAuth authenticatication tokens for mobile and remote apps'); + $o .= t('OAuth authentication tokens for mobile and remote apps'); return $o; } -- cgit v1.2.3 From 78ed1ae44623f58c4e9e2d6fd4d6a4ff322309fd Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Thu, 27 Sep 2018 21:57:27 +0200 Subject: Add translation for new apps --- Zotlabs/Lib/Apps.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 519d5f35a..aef6756b5 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -337,7 +337,20 @@ class Apps { 'Profiles' => t('Profiles'), 'Privacy Groups' => t('Privacy Groups'), 'Notifications' => t('Notifications'), - 'Order Apps' => t('Order Apps') + 'Order Apps' => t('Order Apps'), + 'CalDAV' => t('CalDAV'), + 'CardDAV' => t('CardDAV'), + 'Channel Sources' => t('Channel Sources'), + 'Gallery' => t('Gallery'), + 'Guest Access' => t('Guest Access'), + 'Notes' => t('Notes'), + 'OAuth Apps Manager' => t('OAuth Apps Manager'), + 'OAuth2 Apps Manager' => t('OAuth2 Apps Manager'), + 'PDL Editor' => t('PDL Editor'), + 'Permission Categories' => t('Permission Categories'), + 'Premium Channel' => t('Premium Channel'), + 'Public Stream' => t('Public Stream'), + 'My Chatrooms' => t('My Chatrooms') ); if(array_key_exists('name',$arr)) { @@ -349,6 +362,9 @@ class Apps { for($x = 0; $x < count($arr); $x++) { 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'])); } } } @@ -763,7 +779,6 @@ class Apps { call_hooks('app_list',$hookinfo); $r = $hookinfo['apps']; for($x = 0; $x < count($r); $x ++) { - $r[$x]['app_name']=t(trim($r[$x]['app_name'])); if(! $r[$x]['app_system']) $r[$x]['type'] = 'personal'; $r[$x]['term'] = q("select * from term where otype = %d and oid = %d", -- cgit v1.2.3 From 98b3946fca91fbacb662c14a1545e8eb1982ef3e Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Thu, 27 Sep 2018 23:42:11 +0200 Subject: rename groups and group_members tables for MySQL 8 compatibility --- Zotlabs/Update/_1221.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Zotlabs/Update/_1221.php (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1221.php b/Zotlabs/Update/_1221.php new file mode 100644 index 000000000..252fcaa90 --- /dev/null +++ b/Zotlabs/Update/_1221.php @@ -0,0 +1,20 @@ + Date: Fri, 28 Sep 2018 00:01:39 +0200 Subject: Update Activity_filter.php --- Zotlabs/Widget/Activity_filter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php index 912bfce49..c27a5d48b 100644 --- a/Zotlabs/Widget/Activity_filter.php +++ b/Zotlabs/Widget/Activity_filter.php @@ -47,7 +47,7 @@ class Activity_filter { } if(Apps::system_app_installed(local_channel(), 'Privacy Groups')) { - $groups = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", + $groups = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", intval(local_channel()) ); -- cgit v1.2.3 From 3379f6f79339b7e6b77cd2d8a84e484585a1785a Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:02:58 +0200 Subject: Update Channel.php --- Zotlabs/Module/Settings/Channel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 27a8e695d..73cb4decb 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -63,7 +63,7 @@ class Channel { } $hide_presence = 1 - (intval($role_permissions['online'])); if($role_permissions['default_collection']) { - $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", + $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc( t('Friends') ) ); @@ -71,7 +71,7 @@ class Channel { require_once('include/group.php'); group_add(local_channel(), t('Friends')); group_add_member(local_channel(),t('Friends'),$channel['channel_hash']); - $r = q("select hash from groups where uid = %d and gname = '%s' limit 1", + $r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1", intval(local_channel()), dbesc( t('Friends') ) ); -- cgit v1.2.3 From 07f82e4a148eb11188e3182b42ae5d683c37e298 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:05:43 +0200 Subject: Update Network.php --- Zotlabs/Module/Network.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index ffe605538..e7b150faf 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -108,7 +108,7 @@ class Network extends \Zotlabs\Web\Controller { // filter by collection (e.g. group) if($gid) { - $r = q("SELECT * FROM groups WHERE id = %d AND uid = %d LIMIT 1", + $r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1", intval($gid), intval(local_channel()) ); -- cgit v1.2.3 From 444ae51a3e34438f1d4863c76e114d102d4087a3 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:06:26 +0200 Subject: Update Lockview.php --- Zotlabs/Module/Lockview.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Lockview.php b/Zotlabs/Module/Lockview.php index 466d16997..d7ed07a53 100644 --- a/Zotlabs/Module/Lockview.php +++ b/Zotlabs/Module/Lockview.php @@ -118,7 +118,7 @@ class Lockview extends \Zotlabs\Web\Controller { } if(count($allowed_groups)) { - $r = q("SELECT gname FROM groups WHERE hash IN ( " . implode(', ', $allowed_groups) . " )"); + $r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $allowed_groups) . " )"); if($r) foreach($r as $rr) $l[] = ''; @@ -156,7 +156,7 @@ class Lockview extends \Zotlabs\Web\Controller { if(count($deny_groups)) { - $r = q("SELECT gname FROM groups WHERE hash IN ( " . implode(', ', $deny_groups) . " )"); + $r = q("SELECT gname FROM pgrp WHERE hash IN ( " . implode(', ', $deny_groups) . " )"); if($r) foreach($r as $rr) $l[] = ''; -- cgit v1.2.3 From 4efa5cfa75ac7f6d7e09b049f4304e019083765a Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:10:20 +0200 Subject: Update Group.php --- Zotlabs/Module/Group.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index bf0edb1ed..bfe051d59 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -53,7 +53,7 @@ class Group extends Controller { if((argc() == 2) && (intval(argv(1)))) { check_form_security_token_redirectOnErr('/group', 'group_edit'); - $r = q("SELECT * FROM groups WHERE id = %d AND uid = %d LIMIT 1", + $r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1", intval(argv(1)), intval(local_channel()) ); @@ -67,7 +67,7 @@ class Group extends Controller { $public = intval($_POST['public']); if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) { - $r = q("UPDATE groups SET gname = '%s', visible = %d WHERE uid = %d AND id = %d", + $r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d", dbesc($groupname), intval($public), intval(local_channel()), @@ -115,7 +115,7 @@ class Group extends Controller { $new = (((argc() == 2) && (argv(1) === 'new')) ? true : false); - $groups = q("SELECT id, gname FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", + $groups = q("SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", intval(local_channel()) ); @@ -160,7 +160,7 @@ class Group extends Controller { check_form_security_token_redirectOnErr('/group', 'group_drop', 't'); if(intval(argv(2))) { - $r = q("SELECT gname FROM groups WHERE id = %d AND uid = %d LIMIT 1", + $r = q("SELECT gname FROM pgrp WHERE id = %d AND uid = %d LIMIT 1", intval(argv(2)), intval(local_channel()) ); @@ -192,7 +192,7 @@ class Group extends Controller { if((argc() > 1) && (intval(argv(1)))) { require_once('include/acl_selectors.php'); - $r = q("SELECT * FROM groups WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1", + $r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1", intval(argv(1)), intval(local_channel()) ); -- cgit v1.2.3 From da7bce3470b547e56343d163eb914cc3ddf9339c Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:11:03 +0200 Subject: Update Contactgroup.php --- Zotlabs/Module/Contactgroup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Contactgroup.php b/Zotlabs/Module/Contactgroup.php index 2ba53517f..36aaf7da0 100644 --- a/Zotlabs/Module/Contactgroup.php +++ b/Zotlabs/Module/Contactgroup.php @@ -23,7 +23,7 @@ class Contactgroup extends \Zotlabs\Web\Controller { if((argc() > 1) && (intval(argv(1)))) { - $r = q("SELECT * FROM groups WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1", + $r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1", intval(argv(1)), intval(local_channel()) ); -- cgit v1.2.3 From 978e45911fcda8a607e776aedbdcfe343f32f7a9 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:12:00 +0200 Subject: Update Connections.php --- Zotlabs/Module/Connections.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index 0e5f1dfe2..967e9521d 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -220,7 +220,7 @@ class Connections extends \Zotlabs\Web\Controller { $sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : ""); if($_REQUEST['gid']) { - $sql_extra .= " and xchan_hash in ( select xchan from group_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) "; + $sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) "; } $r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash -- cgit v1.2.3 From 25e8d70786d44b382a5949c9a8b504a6b9ce6a07 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:14:21 +0200 Subject: Update Acl.php --- Zotlabs/Module/Acl.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php index 0c2ad7522..ea131e08c 100644 --- a/Zotlabs/Module/Acl.php +++ b/Zotlabs/Module/Acl.php @@ -81,7 +81,7 @@ class Acl extends \Zotlabs\Web\Controller { if($search) { - $sql_extra = " AND groups.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " "; + $sql_extra = " AND pgrp.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " "; $sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") "; // This horrible mess is needed because position also returns 0 if nothing is found. @@ -128,13 +128,13 @@ class Acl extends \Zotlabs\Web\Controller { // Normal privacy groups - $r = q("SELECT groups.id, groups.hash, groups.gname - FROM groups, group_member - WHERE groups.deleted = 0 AND groups.uid = %d - AND group_member.gid = groups.id + $r = q("SELECT pgrp.id, pgrp.hash, pgrp.gname + FROM pgrp, pgrp_member + WHERE pgrp.deleted = 0 AND pgrp.uid = %d + AND pgrp_member.gid = pgrp.id $sql_extra - GROUP BY groups.id - ORDER BY groups.gname + GROUP BY pgrp.id + ORDER BY pgrp.gname LIMIT %d OFFSET %d", intval(local_channel()), intval($count), -- cgit v1.2.3 From 9afa6cc245184498824014d99f35682ed48af7c8 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:20:03 +0200 Subject: Update Libsync.php --- Zotlabs/Lib/Libsync.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Libsync.php b/Zotlabs/Lib/Libsync.php index 938d484b7..d037a0058 100644 --- a/Zotlabs/Lib/Libsync.php +++ b/Zotlabs/Lib/Libsync.php @@ -122,13 +122,13 @@ class Libsync { } if($groups_changed) { - $r = q("select hash as collection, visible, deleted, gname as name from groups where uid = %d", + $r = q("select hash as collection, visible, deleted, gname as name from pgrp where uid = %d", intval($uid) ); if($r) $info['collections'] = $r; - $r = q("select groups.hash as collection, group_member.xchan as member from groups left join group_member on groups.id = group_member.gid where group_member.uid = %d", + $r = q("select pgrp.hash as collection, pgrp_member.xchan as member from pgrp left join pgrp_member on pgrp.id = pgrp_member.gid where pgrp_member.uid = %d", intval($uid) ); if($r) @@ -464,7 +464,7 @@ class Libsync { // sync collections (privacy groups) oh joy... if(array_key_exists('collections',$arr) && is_array($arr['collections']) && count($arr['collections'])) { - $x = q("select * from groups where uid = %d", + $x = q("select * from pgrp where uid = %d", intval($channel['channel_id']) ); foreach($arr['collections'] as $cl) { @@ -480,7 +480,7 @@ class Libsync { if(($y['gname'] != $cl['name']) || ($y['visible'] != $cl['visible']) || ($y['deleted'] != $cl['deleted'])) { - q("update groups set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d", + q("update pgrp set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d", dbesc($cl['name']), intval($cl['visible']), intval($cl['deleted']), @@ -489,14 +489,14 @@ class Libsync { ); } if(intval($cl['deleted']) && (! intval($y['deleted']))) { - q("delete from group_member where gid = %d", + q("delete from pgrp_member where gid = %d", intval($y['id']) ); } } } if(! $found) { - $r = q("INSERT INTO groups ( hash, uid, visible, deleted, gname ) + $r = q("INSERT INTO pgrp ( hash, uid, visible, deleted, gname ) VALUES( '%s', %d, %d, %d, '%s' ) ", dbesc($cl['collection']), intval($channel['channel_id']), @@ -520,10 +520,10 @@ class Libsync { } } if(! $found_local) { - q("delete from group_member where gid = %d", + q("delete from pgrp_member where gid = %d", intval($y['id']) ); - q("update groups set deleted = 1 where id = %d and uid = %d", + q("update pgrp set deleted = 1 where id = %d and uid = %d", intval($y['id']), intval($channel['channel_id']) ); @@ -533,7 +533,7 @@ class Libsync { } // reload the group list with any updates - $x = q("select * from groups where uid = %d", + $x = q("select * from pgrp where uid = %d", intval($channel['channel_id']) ); @@ -560,7 +560,7 @@ class Libsync { if(isset($y['hash']) && isset($members[$y['hash']])) { foreach($members[$y['hash']] as $member) { $found = false; - $z = q("select xchan from group_member where gid = %d and uid = %d and xchan = '%s' limit 1", + $z = q("select xchan from pgrp_member where gid = %d and uid = %d and xchan = '%s' limit 1", intval($y['id']), intval($channel['channel_id']), dbesc($member) @@ -571,7 +571,7 @@ class Libsync { // if somebody is in the group that wasn't before - add them if(! $found) { - q("INSERT INTO group_member (uid, gid, xchan) + q("INSERT INTO pgrp_member (uid, gid, xchan) VALUES( %d, %d, '%s' ) ", intval($channel['channel_id']), intval($y['id']), @@ -582,7 +582,7 @@ class Libsync { } // now retrieve a list of members we have on this site - $m = q("select xchan from group_member where gid = %d and uid = %d", + $m = q("select xchan from pgrp_member where gid = %d and uid = %d", intval($y['id']), intval($channel['channel_id']) ); @@ -590,7 +590,7 @@ class Libsync { foreach($m as $mm) { // if the local existing member isn't in the list we just received - remove them if(! in_array($mm['xchan'],$members[$y['hash']])) { - q("delete from group_member where xchan = '%s' and gid = %d and uid = %d", + q("delete from pgrp_member where xchan = '%s' and gid = %d and uid = %d", dbesc($mm['xchan']), intval($y['id']), intval($channel['channel_id']) -- cgit v1.2.3 From f4799b2ddb9d64a00a50b122c1a313c0985816d6 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:26:01 +0200 Subject: Update Group.php --- Zotlabs/Lib/Group.php | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Group.php b/Zotlabs/Lib/Group.php index f136a3614..a4ff4fced 100644 --- a/Zotlabs/Lib/Group.php +++ b/Zotlabs/Lib/Group.php @@ -20,11 +20,11 @@ class Group { // access lists. What we're doing here is reviving the dead group, but old content which // was restricted to this group may now be seen by the new group members. - $z = q("SELECT * FROM groups WHERE id = %d LIMIT 1", + $z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1", intval($r) ); if(($z) && $z[0]['deleted']) { - q('UPDATE groups SET deleted = 0 WHERE id = %d', intval($z[0]['id'])); + q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id'])); notice( t('A deleted group with this name was revived. Existing item permissions may apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL); } return true; @@ -34,13 +34,13 @@ class Group { $dups = false; $hash = random_string(32) . str_replace(['<','>'],['.','.'], $name); - $r = q("SELECT id FROM groups WHERE hash = '%s' LIMIT 1", dbesc($hash)); + $r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash)); if($r) $dups = true; } while($dups == true); - $r = q("INSERT INTO groups ( hash, uid, visible, gname ) + $r = q("INSERT INTO pgrp ( hash, uid, visible, gname ) VALUES( '%s', %d, %d, '%s' ) ", dbesc($hash), intval($uid), @@ -58,7 +58,7 @@ class Group { static function remove($uid,$name) { $ret = false; if(x($uid) && x($name)) { - $r = q("SELECT id, hash FROM groups WHERE uid = %d AND gname = '%s' LIMIT 1", + $r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1", intval($uid), dbesc($name) ); @@ -103,13 +103,13 @@ class Group { } // remove all members - $r = q("DELETE FROM group_member WHERE uid = %d AND gid = %d ", + $r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ", intval($uid), intval($group_id) ); // remove group - $r = q("UPDATE groups SET deleted = 1 WHERE uid = %d AND gname = '%s'", + $r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'", intval($uid), dbesc($name) ); @@ -127,7 +127,7 @@ class Group { static function byname($uid,$name) { if((! $uid) || (! strlen($name))) return false; - $r = q("SELECT * FROM groups WHERE uid = %d AND gname = '%s' LIMIT 1", + $r = q("SELECT * FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1", intval($uid), dbesc($name) ); @@ -140,7 +140,7 @@ class Group { static function rec_byhash($uid,$hash) { if((! $uid) || (! strlen($hash))) return false; - $r = q("SELECT * FROM groups WHERE uid = %d AND hash = '%s' LIMIT 1", + $r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1", intval($uid), dbesc($hash) ); @@ -156,7 +156,7 @@ class Group { return false; if(! ( $uid && $gid && $member)) return false; - $r = q("DELETE FROM group_member WHERE uid = %d AND gid = %d AND xchan = '%s' ", + $r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ", intval($uid), intval($gid), dbesc($member) @@ -174,7 +174,7 @@ class Group { if((! $gid) || (! $uid) || (! $member)) return false; - $r = q("SELECT * FROM group_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1", + $r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1", intval($uid), intval($gid), dbesc($member) @@ -184,7 +184,7 @@ class Group { // we indicate success because the group member was in fact created // -- It was just created at another time if(! $r) - $r = q("INSERT INTO group_member (uid, gid, xchan) + $r = q("INSERT INTO pgrp_member (uid, gid, xchan) VALUES( %d, %d, '%s' ) ", intval($uid), intval($gid), @@ -200,9 +200,9 @@ class Group { static function members($gid) { $ret = array(); if(intval($gid)) { - $r = q("SELECT * FROM group_member - LEFT JOIN abook ON abook_xchan = group_member.xchan left join xchan on xchan_hash = abook_xchan - WHERE gid = %d AND abook_channel = %d and group_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ", + $r = q("SELECT * FROM pgrp_member + LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan + WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ", intval($gid), intval(local_channel()), intval(local_channel()) @@ -216,7 +216,7 @@ class Group { static function members_xchan($gid) { $ret = []; if(intval($gid)) { - $r = q("SELECT xchan FROM group_member WHERE gid = %d AND uid = %d", + $r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d", intval($gid), intval(local_channel()) ); @@ -254,7 +254,7 @@ class Group { $grps = []; $o = ''; - $r = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", + $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", intval($uid) ); $grps[] = array('name' => '', 'hash' => '0', 'selected' => ''); @@ -286,7 +286,7 @@ class Group { $groups = array(); - $r = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", + $r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", intval($_SESSION['uid']) ); $member_of = array(); @@ -366,7 +366,7 @@ class Group { stringify_array_elms($x,true); $groups = implode(',', $x); if($groups) { - $r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from groups where hash in ( $groups ))"); + $r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))"); if($r) { foreach($r as $rr) { $ret[] = $rr['xchan']; @@ -379,7 +379,7 @@ class Group { static function member_of($c) { - $r = q("SELECT groups.gname, groups.id FROM groups LEFT JOIN group_member ON group_member.gid = groups.id WHERE group_member.xchan = '%s' AND groups.deleted = 0 ORDER BY groups.gname ASC ", + $r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ", dbesc($c) ); @@ -389,7 +389,7 @@ class Group { static function containing($uid,$c) { - $r = q("SELECT gid FROM group_member WHERE uid = %d AND group_member.xchan = '%s' ", + $r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ", intval($uid), dbesc($c) ); -- cgit v1.2.3 From 5d6c8fd807de99bb3364f7b1aca332e6fa0e84f9 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 00:28:15 +0200 Subject: Update Import.php --- Zotlabs/Module/Import.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php index d031bf16b..c5c52674a 100644 --- a/Zotlabs/Module/Import.php +++ b/Zotlabs/Module/Import.php @@ -428,7 +428,7 @@ class Import extends \Zotlabs\Web\Controller { create_table_from_array('groups', $group); } - $r = q("select * from groups where uid = %d", + $r = q("select * from pgrp where uid = %d", intval($channel['channel_id']) ); if($r) { -- cgit v1.2.3 From fe8b72362286ce55044e38524179e6694acda014 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Thu, 27 Sep 2018 22:42:42 -0400 Subject: Hide form when at or over service_class['limit_identities'] --- Zotlabs/Module/New_channel.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index 97a46a43e..ebdd6c37f 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -142,9 +142,12 @@ class New_channel extends \Zotlabs\Web\Controller { } $limit = account_service_class_fetch(get_account_id(),'total_identities'); - + $canadd = true; if($r && ($limit !== false)) { $channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit); + if ($r[0]['total'] >= $limit) { + $canadd = false; + } } else { $channel_usage_message = ''; @@ -186,7 +189,8 @@ class New_channel extends \Zotlabs\Web\Controller { '$nickname' => $nickname, '$validate' => t('Validate'), '$submit' => t('Create'), - '$channel_usage_message' => $channel_usage_message + '$channel_usage_message' => $channel_usage_message, + '$canadd' => $canadd )); return $o; -- cgit v1.2.3 From 44bb0702030e0c7d6c15e1052b8c49d4cb109157 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 28 Sep 2018 09:55:10 +0200 Subject: add transaction, commit and rollback to update 1221 --- Zotlabs/Update/_1221.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1221.php b/Zotlabs/Update/_1221.php index 252fcaa90..75b400adc 100644 --- a/Zotlabs/Update/_1221.php +++ b/Zotlabs/Update/_1221.php @@ -6,13 +6,18 @@ class _1221 { function run() { + q("START TRANSACTION"); + $r1 = q("ALTER table " . TQUOT . 'groups' . TQUOT . " rename to pgrp "); $r2 = q("ALTER table " . TQUOT . 'group_member' . TQUOT . " rename to pgrp_member "); if($r1 && $r2) { + q("COMMIT"); return UPDATE_SUCCESS; } + + q("ROLLBACK"); return UPDATE_FAILED; } -- cgit v1.2.3 From 20285d076b789f2e08d83e2fb7c89d017a4135ed Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 28 Sep 2018 11:29:05 +0200 Subject: settings for channel home --- Zotlabs/Module/Settings/Channel_home.php | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Zotlabs/Module/Settings/Channel_home.php (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Channel_home.php b/Zotlabs/Module/Settings/Channel_home.php new file mode 100644 index 000000000..1d1cc370b --- /dev/null +++ b/Zotlabs/Module/Settings/Channel_home.php @@ -0,0 +1,43 @@ + $rpath, + '$action_url' => 'settings/' . $module, + '$form_security_token' => get_form_security_token('settings_' . $module), + '$title' => t('Channel Home Settings'), + '$features' => process_module_features_get(local_channel(), $features), + '$submit' => t('Submit') + )); + + return $o; + } + +} -- cgit v1.2.3 From d7a20821c3b5920715384e1256315fdddd4ba96b Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 28 Sep 2018 11:32:00 +0200 Subject: move display settings up --- Zotlabs/Widget/Settings_menu.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index 92f615452..238b8071e 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -45,11 +45,6 @@ class Settings_menu { ); - $tabs[] = array( - 'label' => t('Addon settings'), - 'url' => z_root().'/settings/featured', - 'selected' => ((argv(1) === 'featured') ? 'active' : ''), - ); $tabs[] = array( 'label' => t('Display settings'), @@ -57,6 +52,12 @@ class Settings_menu { '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 52fea09c53883cf1d9ca96a642acf7b2caa79cb2 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:23:38 +0200 Subject: add translations --- Zotlabs/Module/Oauth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php index fbcc48ead..a0a6f37cb 100644 --- a/Zotlabs/Module/Oauth.php +++ b/Zotlabs/Module/Oauth.php @@ -97,7 +97,7 @@ class Oauth extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'OAuth Apps Manager App (Not Installed):
'; + $o = '' . t('OAuth Apps Manager App (Not Installed):') . '
'; $o .= t('OAuth authentication tokens for mobile and remote apps'); return $o; } -- cgit v1.2.3 From 21272735ae92f58f9af78c00363d66199d96bb19 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:24:45 +0200 Subject: Update Oauth2.php --- Zotlabs/Module/Oauth2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth2.php b/Zotlabs/Module/Oauth2.php index c27d7534b..608da6d51 100644 --- a/Zotlabs/Module/Oauth2.php +++ b/Zotlabs/Module/Oauth2.php @@ -103,7 +103,7 @@ class Oauth2 extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'OAuth2 Apps Manager App (Not Installed):
'; + $o = '' . t('OAuth2 Apps Manager App (Not Installed):') . '
'; $o .= t('OAuth2 authenticatication tokens for mobile and remote apps'); return $o; } -- cgit v1.2.3 From 598fe914647616a9ad3c8567b462e9f26cc190ef Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:25:38 +0200 Subject: Update Pdledit.php --- Zotlabs/Module/Pdledit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php index d0bde7715..cd5ec3709 100644 --- a/Zotlabs/Module/Pdledit.php +++ b/Zotlabs/Module/Pdledit.php @@ -39,7 +39,7 @@ class Pdledit extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'PDL Editor App (Not Installed):
'; + $o = '' . t('PDL Editor App (Not Installed):') . '
'; $o .= t('Provides the ability to edit system page layouts'); return $o; } -- cgit v1.2.3 From 02a16050d9fd05ef36a47b004b8d99760e0b19dc Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:26:09 +0200 Subject: Update Permcats.php --- Zotlabs/Module/Permcats.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php index 3d068862a..f966be147 100644 --- a/Zotlabs/Module/Permcats.php +++ b/Zotlabs/Module/Permcats.php @@ -59,7 +59,7 @@ class Permcats extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Permission Categories App (Not Installed):
'; + $o = '' . t('Permission Categories App (Not Installed):') . '
'; $o .= t('Create custom connection permission limits'); return $o; } -- cgit v1.2.3 From f7e94546977f8e38b69bf27515ed2dc0cdc93b86 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:26:46 +0200 Subject: Update Poke.php --- Zotlabs/Module/Poke.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Poke.php b/Zotlabs/Module/Poke.php index 46dcf6dd3..4074663ae 100644 --- a/Zotlabs/Module/Poke.php +++ b/Zotlabs/Module/Poke.php @@ -162,7 +162,7 @@ class Poke extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Poke App (Not Installed):
'; + $o = '' . t('Poke App (Not Installed):') . '
'; $o .= t('Poke somebody in your addressbook'); return $o; } -- cgit v1.2.3 From 86fc5b5ed82d8a764699929e477ef104d540d802 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:27:16 +0200 Subject: Update Sources.php --- Zotlabs/Module/Sources.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Sources.php b/Zotlabs/Module/Sources.php index 5d05244a7..f761d5666 100644 --- a/Zotlabs/Module/Sources.php +++ b/Zotlabs/Module/Sources.php @@ -85,7 +85,7 @@ class Sources extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Sources App (Not Installed):
'; + $o = '' . t('Sources App (Not Installed):') . '
'; $o .= t('Automatically import channel content from other channels or feeds'); return $o; } -- cgit v1.2.3 From eb2c2b94005b70686e683a8bee59fa6a3db0ed57 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:27:54 +0200 Subject: Update Tokens.php --- Zotlabs/Module/Tokens.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Tokens.php b/Zotlabs/Module/Tokens.php index ae03a499a..d2198331a 100644 --- a/Zotlabs/Module/Tokens.php +++ b/Zotlabs/Module/Tokens.php @@ -96,7 +96,7 @@ class Tokens extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Guest Access App (Not Installed):
'; + $o = '' . t('Guest Access App (Not Installed):') . '
'; $o .= t('Create access tokens so that non-members can access private content'); return $o; } -- cgit v1.2.3 From db006b911accbada8a241d8c981ce46881f6e488 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:28:57 +0200 Subject: Update Webpages.php --- Zotlabs/Module/Webpages.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index c6599db3b..79fd51d33 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -45,7 +45,7 @@ class Webpages extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Webpages App (Not Installed):
'; + $o = '' . t('Webpages App (Not Installed):') . '
'; $o .= t('Provide managed web pages on your channel'); return $o; } -- cgit v1.2.3 From 90e9948dbe98f96e17de25a942361e1f170b9568 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:29:33 +0200 Subject: Update Wiki.php --- Zotlabs/Module/Wiki.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 0fb5a4605..80824b7d5 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -49,7 +49,7 @@ class Wiki extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Wiki App (Not Installed):
'; + $o = '' . t('Wiki App (Not Installed):') . '
'; $o .= t('Provide a wiki for your channel'); return $o; } -- cgit v1.2.3 From 24c7bb600e9d22269243ac229a94438b093e8716 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:30:03 +0200 Subject: Update Articles.php --- Zotlabs/Module/Articles.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index 7af1ab6b8..1a9691b6a 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -40,7 +40,7 @@ class Articles extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Articles App (Not Installed):
'; + $o = '' . t('Articles App (Not Installed):') . '
'; $o .= t('Create interactive articles'); return $o; } -- cgit v1.2.3 From 134529a09d1894280f33241355e385b9eddb95f0 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:30:30 +0200 Subject: Update Cards.php --- Zotlabs/Module/Cards.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 78cbad5fd..8aca60e57 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -43,7 +43,7 @@ class Cards extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Cards App (Not Installed):
'; + $o = '' . t('Cards App (Not Installed):') . '
'; $o .= t('Create personal planning cards'); return $o; } -- cgit v1.2.3 From d8c6d93c6e564b166275bdcd730a5251dfdd7304 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:31:22 +0200 Subject: Update Cdav.php --- Zotlabs/Module/Cdav.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index 7142615d5..860864e99 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -836,7 +836,7 @@ class Cdav extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'CalDAV App (Not Installed):
'; + $o = '' . t('CalDAV App (Not Installed):') . '
'; $o .= t('CalDAV capable calendar'); return $o; } @@ -845,7 +845,7 @@ class Cdav extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'CardDAV App (Not Installed):
'; + $o = '' . t('CardDAV App (Not Installed):') . '
'; $o .= t('CalDAV capable addressbook'); return $o; } -- cgit v1.2.3 From 2811d6ae53b32c132d2589871ba8b0a267675eef Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:32:27 +0200 Subject: Update Chat.php --- Zotlabs/Module/Chat.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index 551dc5e2a..d007ec407 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -99,7 +99,7 @@ class Chat extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Chatrooms App (Not Installed):
'; + $o = '' . t('Chatrooms App (Not Installed):') . '
'; $o .= t('Access Controlled Chatrooms'); return $o; } -- cgit v1.2.3 From 7fd332f8cf2ba77fe16192f4e02d657283a3c25c Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:33:17 +0200 Subject: Update Connect.php --- Zotlabs/Module/Connect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Connect.php b/Zotlabs/Module/Connect.php index 7194e7039..83f0f455d 100644 --- a/Zotlabs/Module/Connect.php +++ b/Zotlabs/Module/Connect.php @@ -101,7 +101,7 @@ class Connect extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Premium Channel App (Not Installed):
'; + $o = '' . t('Premium Channel App (Not Installed):') . '
'; $o .= t('Allows you to set restrictions and terms on those that connect with your channel'); return $o; } -- cgit v1.2.3 From a23724838813cfa82007dbff78b8edcd5c95381f Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:33:50 +0200 Subject: Update Group.php --- Zotlabs/Module/Group.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index bfe051d59..c544f95a0 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -98,7 +98,7 @@ class Group extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Privacy Groups App (Not Installed):
'; + $o = '' . t('Privacy Groups App (Not Installed):') . '
'; $o .= t('Management of privacy groups'); return $o; } -- cgit v1.2.3 From ba417894edcfafd6d625ed9e27835362471b1e3a Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:34:20 +0200 Subject: Update Invite.php --- Zotlabs/Module/Invite.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php index 234802746..8640c5b23 100644 --- a/Zotlabs/Module/Invite.php +++ b/Zotlabs/Module/Invite.php @@ -107,7 +107,7 @@ class Invite extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Invite App (Not Installed):
'; + $o = '' . t('Invite App (Not Installed):') . '
'; $o .= t('Send email invitations to join this network'); return $o; } -- cgit v1.2.3 From e2115e8ea5b7de6cde8f0dd0bef941448fae9b09 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:34:45 +0200 Subject: Update Lang.php --- Zotlabs/Module/Lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Lang.php b/Zotlabs/Module/Lang.php index 9858beecd..a163da102 100644 --- a/Zotlabs/Module/Lang.php +++ b/Zotlabs/Module/Lang.php @@ -14,7 +14,7 @@ class Lang extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Language App (Not Installed):
'; + $o = '' . t('Language App (Not Installed):') . '
'; $o .= t('Change UI language'); return $o; } -- cgit v1.2.3 From 58d9ca1bfd5a9e696a0e7d13d915dde4db5a67a2 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:35:14 +0200 Subject: Update Mood.php --- Zotlabs/Module/Mood.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Mood.php b/Zotlabs/Module/Mood.php index cceef5ffa..4ffb35ca8 100644 --- a/Zotlabs/Module/Mood.php +++ b/Zotlabs/Module/Mood.php @@ -129,7 +129,7 @@ class Mood extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = 'Mood App (Not Installed):
'; + $o = '' . t('Mood App (Not Installed):') . '
'; $o .= t('Set your current mood and tell your friends'); return $o; } -- cgit v1.2.3 From c13d7e29ef9676b0f0e4ae23aa52e203f4ad8895 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 15:35:39 +0200 Subject: Update Notes.php --- Zotlabs/Module/Notes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php index cd383a6c2..2916925e2 100644 --- a/Zotlabs/Module/Notes.php +++ b/Zotlabs/Module/Notes.php @@ -52,7 +52,7 @@ class Notes extends Controller { //Do not display any associated widgets at this point App::$pdl = EMPTY_STR; - $o = 'Notes App (Not Installed):
'; + $o = '' . t('Notes App (Not Installed):') . '
'; $o .= t('A simple notes app with a widget (note: notes are not encrypted)'); return $o; } -- cgit v1.2.3 From 5f7d83bd4d1a5e9e22d05ebda8ed1e82492d0094 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:44:10 +0200 Subject: Update Articles.php --- Zotlabs/Module/Articles.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index 1a9691b6a..ad4d67c4e 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -40,7 +40,7 @@ class Articles extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Articles App (Not Installed):') . '
'; + $o = '' . t('Articles App') . ' (' . t('Not Installed') . '):
'; $o .= t('Create interactive articles'); return $o; } -- cgit v1.2.3 From 5c8e1169cd3be8c569bf54c58a6a4f473dd6b6f3 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:45:11 +0200 Subject: Update Cards.php --- Zotlabs/Module/Cards.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 8aca60e57..3656860a5 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -43,7 +43,7 @@ class Cards extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Cards App (Not Installed):') . '
'; + $o = '' . t('Cards App') . ' (' . t('Not Installed') . '):
'; $o .= t('Create personal planning cards'); return $o; } -- cgit v1.2.3 From c6fce5de24df96cb8048543fb6b8a6907ecaa610 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:46:04 +0200 Subject: Update Cdav.php --- Zotlabs/Module/Cdav.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php index 860864e99..d644e48b1 100644 --- a/Zotlabs/Module/Cdav.php +++ b/Zotlabs/Module/Cdav.php @@ -836,7 +836,7 @@ class Cdav extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('CalDAV App (Not Installed):') . '
'; + $o = '' . t('CalDAV App') . ' (' . t('Not Installed') . '):
'; $o .= t('CalDAV capable calendar'); return $o; } @@ -845,7 +845,7 @@ class Cdav extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('CardDAV App (Not Installed):') . '
'; + $o = '' . t('CardDAV App') . ' (' . t('Not Installed') . '):
'; $o .= t('CalDAV capable addressbook'); return $o; } -- cgit v1.2.3 From b3249c10c24cb2b06a1d43581d270f78183e8d61 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:46:20 +0200 Subject: Update Chat.php --- Zotlabs/Module/Chat.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index d007ec407..db77e2612 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -99,7 +99,7 @@ class Chat extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Chatrooms App (Not Installed):') . '
'; + $o = '' . t('Chatrooms App') . ' (' . t('Not Installed') . '):
'; $o .= t('Access Controlled Chatrooms'); return $o; } -- cgit v1.2.3 From cb768ea23f81d35b18204ae1747240a586541d45 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:46:36 +0200 Subject: Update Connect.php --- Zotlabs/Module/Connect.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Connect.php b/Zotlabs/Module/Connect.php index 83f0f455d..62d3af840 100644 --- a/Zotlabs/Module/Connect.php +++ b/Zotlabs/Module/Connect.php @@ -101,7 +101,7 @@ class Connect extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Premium Channel App (Not Installed):') . '
'; + $o = '' . t('Premium Channel App') . ' (' . t('Not Installed') . '):
'; $o .= t('Allows you to set restrictions and terms on those that connect with your channel'); return $o; } -- cgit v1.2.3 From f07a4667b6168c26ec09d34a14b1dafa00d69a58 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:47:20 +0200 Subject: Update Invite.php --- Zotlabs/Module/Invite.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php index 8640c5b23..6359da54c 100644 --- a/Zotlabs/Module/Invite.php +++ b/Zotlabs/Module/Invite.php @@ -107,7 +107,7 @@ class Invite extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Invite App (Not Installed):') . '
'; + $o = '' . t('Invite App') . ' (' . t('Not Installed') . '):
'; $o .= t('Send email invitations to join this network'); return $o; } -- cgit v1.2.3 From accb21128008dd4a9114159eec0fd6e872873b16 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:47:37 +0200 Subject: Update Lang.php --- Zotlabs/Module/Lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Lang.php b/Zotlabs/Module/Lang.php index a163da102..a32f933a6 100644 --- a/Zotlabs/Module/Lang.php +++ b/Zotlabs/Module/Lang.php @@ -14,7 +14,7 @@ class Lang extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Language App (Not Installed):') . '
'; + $o = '' . t('Language App') . ' (' . t('Not Installed') . '):
'; $o .= t('Change UI language'); return $o; } -- cgit v1.2.3 From e3e96e59d2e15b655931ecb5168eda059582ab8a Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:47:52 +0200 Subject: Update Mood.php --- Zotlabs/Module/Mood.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Mood.php b/Zotlabs/Module/Mood.php index 4ffb35ca8..16ef0b171 100644 --- a/Zotlabs/Module/Mood.php +++ b/Zotlabs/Module/Mood.php @@ -129,7 +129,7 @@ class Mood extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Mood App (Not Installed):') . '
'; + $o = '' . t('Mood App') . ' (' . t('Not Installed') . '):
'; $o .= t('Set your current mood and tell your friends'); return $o; } -- cgit v1.2.3 From c34c0c671883385145b6cda7bb84ace143b55bd6 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:48:09 +0200 Subject: Update Notes.php --- Zotlabs/Module/Notes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Notes.php b/Zotlabs/Module/Notes.php index 2916925e2..178a6bce0 100644 --- a/Zotlabs/Module/Notes.php +++ b/Zotlabs/Module/Notes.php @@ -52,7 +52,7 @@ class Notes extends Controller { //Do not display any associated widgets at this point App::$pdl = EMPTY_STR; - $o = '' . t('Notes App (Not Installed):') . '
'; + $o = '' . t('Notes App') . ' (' . t('Not Installed') . '):
'; $o .= t('A simple notes app with a widget (note: notes are not encrypted)'); return $o; } -- cgit v1.2.3 From 423e1422ef00f69a54322836f3b6df671b054e77 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:48:25 +0200 Subject: Update Oauth.php --- Zotlabs/Module/Oauth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth.php b/Zotlabs/Module/Oauth.php index a0a6f37cb..27c062df2 100644 --- a/Zotlabs/Module/Oauth.php +++ b/Zotlabs/Module/Oauth.php @@ -97,7 +97,7 @@ class Oauth extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('OAuth Apps Manager App (Not Installed):') . '
'; + $o = '' . t('OAuth Apps Manager App') . ' (' . t('Not Installed') . '):
'; $o .= t('OAuth authentication tokens for mobile and remote apps'); return $o; } -- cgit v1.2.3 From c8399e8104b44273052581c5bbdb77debbe5b75e Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:48:44 +0200 Subject: Update Oauth2.php --- Zotlabs/Module/Oauth2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Oauth2.php b/Zotlabs/Module/Oauth2.php index 608da6d51..db2687b4c 100644 --- a/Zotlabs/Module/Oauth2.php +++ b/Zotlabs/Module/Oauth2.php @@ -103,7 +103,7 @@ class Oauth2 extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('OAuth2 Apps Manager App (Not Installed):') . '
'; + $o = '' . t('OAuth2 Apps Manager App') . ' (' . t('Not Installed') . '):
'; $o .= t('OAuth2 authenticatication tokens for mobile and remote apps'); return $o; } -- cgit v1.2.3 From 5500473387e16772cc4feb7c3821b733b0b08157 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:49:02 +0200 Subject: Update Pdledit.php --- Zotlabs/Module/Pdledit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Pdledit.php b/Zotlabs/Module/Pdledit.php index cd5ec3709..5cedb29a8 100644 --- a/Zotlabs/Module/Pdledit.php +++ b/Zotlabs/Module/Pdledit.php @@ -39,7 +39,7 @@ class Pdledit extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('PDL Editor App (Not Installed):') . '
'; + $o = '' . t('PDL Editor App') . ' (' . t('Not Installed') . '):
'; $o .= t('Provides the ability to edit system page layouts'); return $o; } -- cgit v1.2.3 From 23d5e15f0f9d3502f6c5c4163f93de5c9618cda1 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:49:20 +0200 Subject: Update Permcats.php --- Zotlabs/Module/Permcats.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php index f966be147..262a14fe4 100644 --- a/Zotlabs/Module/Permcats.php +++ b/Zotlabs/Module/Permcats.php @@ -59,7 +59,7 @@ class Permcats extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Permission Categories App (Not Installed):') . '
'; + $o = '' . t('Permission Categories App') . ' (' . t('Not Installed') . '):
'; $o .= t('Create custom connection permission limits'); return $o; } -- cgit v1.2.3 From 01043fa790116a89619c0a0fe9c12bd566db8cc7 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:49:42 +0200 Subject: Update Poke.php --- Zotlabs/Module/Poke.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Poke.php b/Zotlabs/Module/Poke.php index 4074663ae..1f1edfa18 100644 --- a/Zotlabs/Module/Poke.php +++ b/Zotlabs/Module/Poke.php @@ -162,7 +162,7 @@ class Poke extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Poke App (Not Installed):') . '
'; + $o = '' . t('Poke App') . ' (' . t('Not Installed') . '):
'; $o .= t('Poke somebody in your addressbook'); return $o; } -- cgit v1.2.3 From 6d3c1fb7fcc5bfb56bbcf846bf939c1a6aeff3c4 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:49:56 +0200 Subject: Update Sources.php --- Zotlabs/Module/Sources.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Sources.php b/Zotlabs/Module/Sources.php index f761d5666..e535f6ebf 100644 --- a/Zotlabs/Module/Sources.php +++ b/Zotlabs/Module/Sources.php @@ -85,7 +85,7 @@ class Sources extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Sources App (Not Installed):') . '
'; + $o = '' . t('Sources App') . ' (' . t('Not Installed') . '):
'; $o .= t('Automatically import channel content from other channels or feeds'); return $o; } -- cgit v1.2.3 From 8e673a6cdf9305b0b93313b568759fbde655ee36 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:50:15 +0200 Subject: Update Tokens.php --- Zotlabs/Module/Tokens.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Tokens.php b/Zotlabs/Module/Tokens.php index d2198331a..1ba41dcc5 100644 --- a/Zotlabs/Module/Tokens.php +++ b/Zotlabs/Module/Tokens.php @@ -96,7 +96,7 @@ class Tokens extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Guest Access App (Not Installed):') . '
'; + $o = '' . t('Guest Access App') . ' (' . t('Not Installed') . '):
'; $o .= t('Create access tokens so that non-members can access private content'); return $o; } -- cgit v1.2.3 From 9b0d12321703cefa37d9e89c3014ceb477074fab Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:50:29 +0200 Subject: Update Webpages.php --- Zotlabs/Module/Webpages.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index 79fd51d33..c9b2264bf 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -45,7 +45,7 @@ class Webpages extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Webpages App (Not Installed):') . '
'; + $o = '' . t('Webpages App') . ' (' . t('Not Installed') . '):
'; $o .= t('Provide managed web pages on your channel'); return $o; } -- cgit v1.2.3 From 403ead44f92a52f2dce6b79e5d2d79ffe167e1a4 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:50:45 +0200 Subject: Update Wiki.php --- Zotlabs/Module/Wiki.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 80824b7d5..6be39214e 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -49,7 +49,7 @@ class Wiki extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Wiki App (Not Installed):') . '
'; + $o = '' . t('Wiki App') . ' (' . t('Not Installed') . '):
'; $o .= t('Provide a wiki for your channel'); return $o; } -- cgit v1.2.3 From c45a9504e7c4fe8add92276deecb1866c2a388bf Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 28 Sep 2018 19:52:11 +0200 Subject: Update Group.php --- Zotlabs/Module/Group.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index c544f95a0..c8ccaa2cb 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -98,7 +98,7 @@ class Group extends Controller { //Do not display any associated widgets at this point App::$pdl = ''; - $o = '' . t('Privacy Groups App (Not Installed):') . '
'; + $o = '' . t('Privacy Groups App') . ' (' . t('Not Installed') . '):
'; $o .= t('Management of privacy groups'); return $o; } -- cgit v1.2.3 From 5f992ffe154ed9e2b225c9a1b3d7c47d39e41d34 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Sat, 29 Sep 2018 00:17:55 +0200 Subject: Remove servicelevel logic --- Zotlabs/Lib/ThreadItem.php | 2 +- Zotlabs/Module/Admin/Account_edit.php | 5 ++--- Zotlabs/Module/Admin/Site.php | 24 ------------------------ Zotlabs/Module/Item.php | 22 ---------------------- Zotlabs/Module/Mail.php | 2 +- Zotlabs/Module/New_channel.php | 2 -- Zotlabs/Module/Register.php | 5 ----- Zotlabs/Module/Settings/Account.php | 15 --------------- Zotlabs/Module/Settings/Channel.php | 7 +------ 9 files changed, 5 insertions(+), 79 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index ac24806a6..48018f66c 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -274,7 +274,7 @@ class ThreadItem { $has_bookmarks = false; if(is_array($item['term'])) { foreach($item['term'] as $t) { - if((get_account_techlevel() > 0) && ($t['ttype'] == TERM_BOOKMARK)) + if(($t['ttype'] == TERM_BOOKMARK)) $has_bookmarks = true; } } diff --git a/Zotlabs/Module/Admin/Account_edit.php b/Zotlabs/Module/Admin/Account_edit.php index 6dfadf183..0300fb10c 100644 --- a/Zotlabs/Module/Admin/Account_edit.php +++ b/Zotlabs/Module/Admin/Account_edit.php @@ -31,7 +31,7 @@ class Account_edit { } $service_class = trim($_REQUEST['service_class']); - $account_level = intval(trim($_REQUEST['account_level'])); + $account_level = 5; $account_language = trim($_REQUEST['account_language']); $r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s' @@ -68,7 +68,6 @@ class Account_edit { '$title' => t('Account Edit'), '$pass1' => [ 'pass1', t('New Password'), ' ','' ], '$pass2' => [ 'pass2', t('New Password again'), ' ','' ], - '$account_level' => [ 'account_level', t('Technical skill level'), $x[0]['account_level'], '', \Zotlabs\Lib\Techlevels::levels() ], '$account_language' => [ 'account_language' , t('Account language (for emails)'), $x[0]['account_language'], '', language_list() ], '$service_class' => [ 'service_class', t('Service class'), $x[0]['account_service_class'], '' ], '$submit' => t('Submit'), @@ -81,4 +80,4 @@ class Account_edit { } -} \ No newline at end of file +} diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index 5912a7c97..e67f9f165 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -72,7 +72,6 @@ class Site { $maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50); $feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0); $verify_email = ((x($_POST,'verify_email')) ? 1 : 0); - $techlevel_lock = ((x($_POST,'techlock')) ? intval($_POST['techlock']) : 0); $imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : ''); $thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0); $force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000); @@ -81,10 +80,6 @@ class Site { $permissions_role = escape_tags(trim($_POST['permissions_role'])); - $techlevel = null; - if(array_key_exists('techlevel', $_POST)) - $techlevel = intval($_POST['techlevel']); - set_config('system', 'feed_contacts', $feed_contacts); set_config('system', 'delivery_interval', $delivery_interval); set_config('system', 'delivery_batch_count', $delivery_batch_count); @@ -110,12 +105,6 @@ class Site { set_config('system', 'pubstream_incl',$pub_incl); set_config('system', 'pubstream_excl',$pub_excl); - set_config('system', 'techlevel_lock', $techlevel_lock); - - - - if(! is_null($techlevel)) - set_config('system', 'techlevel', $techlevel); if($directory_server) set_config('system','directory_server',$directory_server); @@ -284,15 +273,6 @@ class Site { // now invert the logic for the setting. $discover_tab = (1 - $discover_tab); - $techlevels = [ - '0' => t('Beginner/Basic'), - '1' => t('Novice - not skilled but willing to learn'), - '2' => t('Intermediate - somewhat comfortable'), - '3' => t('Advanced - very comfortable'), - '4' => t('Expert - I can write computer code'), - '5' => t('Wizard - I probably know more than you do') - ]; - $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); $default_role = get_config('system','default_permissions_role','social'); @@ -316,10 +296,6 @@ class Site { // name, label, value, help string, extra data... '$sitename' => array('sitename', t("Site name"), htmlspecialchars(get_config('system','sitename'), ENT_QUOTES, 'UTF-8'),''), - '$techlevel' => [ 'techlevel', t('Site default technical skill level'), get_config('system','techlevel'), t('Used to provide a member experience matched to technical comfort level'), $techlevels ], - - '$techlock' => [ 'techlock', t('Lock the technical skill level setting'), get_config('system','techlevel_lock'), t('Members can set their own technical comfort level by default') ], - '$banner' => array('banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed')), '$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")), '$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")), diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index a24d6da9c..2ee639874 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -1165,28 +1165,6 @@ class Item extends \Zotlabs\Web\Controller { return $ret; } - // auto-upgrade beginner (techlevel 0) accounts - if they have at least two friends and ten posts - // and have uploaded something (like a profile photo), promote them to level 1. - - $a = q("select account_id, account_level from account where account_id = (select channel_account_id from channel where channel_id = %d limit 1)", - intval($channel_id) - ); - if((! intval($a[0]['account_level'])) && intval($r[0]['total']) > 10) { - $x = q("select count(abook_id) as total from abook where abook_channel = %d", - intval($channel_id) - ); - if($x && intval($x[0]['total']) > 2) { - $y = q("select count(id) as total from attach where uid = %d", - intval($channel_id) - ); - if($y && intval($y[0]['total']) > 1) { - q("update account set account_level = 1 where account_id = %d limit 1", - intval($a[0]['account_id']) - ); - } - } - } - if (!$iswebpage) { $max = engr_units_to_bytes(service_class_fetch($channel_id,'total_items')); if(! service_class_allows($channel_id,'total_items',$r[0]['total'])) { diff --git a/Zotlabs/Module/Mail.php b/Zotlabs/Module/Mail.php index ca183f644..d38c1d88c 100644 --- a/Zotlabs/Module/Mail.php +++ b/Zotlabs/Module/Mail.php @@ -393,7 +393,7 @@ class Mail extends \Zotlabs\Web\Controller { 'delete' => t('Delete message'), 'dreport' => t('Delivery report'), 'recall' => t('Recall message'), - 'can_recall' => (($channel['channel_hash'] == $message['from_xchan'] && get_account_techlevel() > 0) ? true : false), + 'can_recall' => ($channel['channel_hash'] == $message['from_xchan']), 'is_recalled' => (intval($message['mail_recalled']) ? t('Message has been recalled.') : ''), 'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c'), ); diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index ebdd6c37f..a9022a03a 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -171,8 +171,6 @@ class New_channel extends \Zotlabs\Web\Controller { $privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" ); $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); - if((get_account_techlevel() < 4) && $privacy_role !== 'custom') - unset($perm_roles[t('Other')]); $name = array('name', t('Channel name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), $name_help, "*"); $nickhub = '@' . \App::get_hostname(); diff --git a/Zotlabs/Module/Register.php b/Zotlabs/Module/Register.php index 3dded19c7..f9d81be0c 100644 --- a/Zotlabs/Module/Register.php +++ b/Zotlabs/Module/Register.php @@ -227,11 +227,6 @@ class Register extends \Zotlabs\Web\Controller { $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); - // A new account will not have a techlevel, but accounts can also be created by the administrator. - - if((get_account_techlevel() < 4) && $privacy_role !== 'custom') - unset($perm_roles[t('Other')]); - // Configurable terms of service link $tosurl = get_config('system','tos_url'); diff --git a/Zotlabs/Module/Settings/Account.php b/Zotlabs/Module/Settings/Account.php index 9643c5958..b40f516ca 100644 --- a/Zotlabs/Module/Settings/Account.php +++ b/Zotlabs/Module/Settings/Account.php @@ -12,7 +12,6 @@ class Account { $errs = array(); $email = ((x($_POST,'email')) ? trim(notags($_POST['email'])) : ''); - $techlevel = ((array_key_exists('techlevel',$_POST)) ? intval($_POST['techlevel']) : 0); $account = \App::get_account(); if($email != $account['account_email']) { @@ -32,13 +31,6 @@ class Account { $errs[] = t('System failure storing new email. Please try again.'); } } - if($techlevel != $account['account_level']) { - $r = q("update account set account_level = %d where account_id = %d", - intval($techlevel), - intval($account['account_id']) - ); - info( t('Technical skill level updated') . EOL); - } if($errs) { foreach($errs as $err) @@ -101,11 +93,6 @@ class Account { $email = \App::$account['account_email']; - $techlevels = \Zotlabs\Lib\Techlevels::levels(); - - $def_techlevel = \App::$account['account_level']; - $techlock = get_config('system','techlevel_lock'); - $tpl = get_markup_template("settings_account.tpl"); $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("settings_account"), @@ -113,8 +100,6 @@ class Account { '$origpass' => array('origpass', t('Current Password'), ' ',''), '$password1'=> array('npassword', t('Enter New Password'), '', ''), '$password2'=> array('confirm', t('Confirm New Password'), '', t('Leave password fields blank unless changing')), - '$techlevel' => [ 'techlevel', t('Your technical skill level'), $def_techlevel, t('Used to provide a member experience and additional features consistent with your comfort level'), $techlevels ], - '$techlock' => $techlock, '$submit' => t('Submit'), '$email' => array('email', t('Email Address:'), $email, ''), '$removeme' => t('Remove Account'), diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 73cb4decb..c473a70a4 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -432,7 +432,7 @@ class Channel { '$nickname' => (($intl_nickname === $webbie) ? $webbie : $intl_nickname . ' (' . $webbie . ')'), '$subdir' => $subdir, '$davdesc' => t('Your files/photos are accessible via WebDAV at'), - '$davpath' => ((get_account_techlevel() > 3) ? z_root() . '/dav/' . $nickname : ''), + '$davpath' => z_root() . '/dav/' . $nickname, '$basepath' => \App::get_hostname() )); @@ -490,11 +490,6 @@ class Channel { $permissions_set = (($permissions_role != 'custom') ? true : false); $perm_roles = \Zotlabs\Access\PermissionRoles::roles(); - if((get_account_techlevel() < 4) && $permissions_role !== 'custom') - unset($perm_roles[t('Other')]); - - - $vnotify = get_pconfig(local_channel(),'system','vnotify'); $always_show_in_notices = get_pconfig(local_channel(),'system','always_show_in_notices'); -- cgit v1.2.3 From 7ca8f7b5ccd8f0526d7b96676a15440d8068d58d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 29 Sep 2018 15:42:22 +0200 Subject: allow to install apps by name --- Zotlabs/Lib/Apps.php | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index aef6756b5..c54a5a111 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -546,6 +546,17 @@ class Apps { } static public function app_install($uid,$app) { + + if(! is_array($app)) { + $r = q("select * from app where app_name = '%s' and app_channel = 0", + dbesc($app) + ); + if(! $r) + return false; + + $app = self::app_encode($r[0]); + } + $app['uid'] = $uid; if(self::app_installed($uid,$app,true)) -- cgit v1.2.3 From 6eeac03a0e42ae88218b76948aedfa541022718c Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 29 Sep 2018 16:00:34 +0200 Subject: appman: query terms also by uid to prevent double entries --- Zotlabs/Module/Appman.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php index 3ebafafa4..f50dcc2ab 100644 --- a/Zotlabs/Module/Appman.php +++ b/Zotlabs/Module/Appman.php @@ -113,10 +113,12 @@ class Appman extends \Zotlabs\Web\Controller { if($r) { $app = $r[0]; - $term = q("select * from term where otype = %d and oid = %d", + $term = q("select * from term where otype = %d and oid = %d and uid = %d", intval(TERM_OBJ_APP), - intval($r[0]['id']) + intval($r[0]['id']), + intval(local_channel()) ); + if($term) { $app['categories'] = ''; foreach($term as $t) { -- cgit v1.2.3 From 5906d6cce373df81458bf16d461bee9705fed3a6 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 29 Sep 2018 18:00:14 +0200 Subject: improve network search --- Zotlabs/Module/Network.php | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index e7b150faf..73f09f90b 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -84,18 +84,7 @@ class Network extends \Zotlabs\Web\Controller { $search = (($_GET['search']) ? $_GET['search'] : ''); if($search) { - $_GET['netsearch'] = escape_tags($search); - if(strpos($search,'@') === 0) { - $r = q("select abook_id from abook left join xchan on abook_xchan = xchan_hash where xchan_name = '%s' and abook_channel = %d limit 1", - dbesc(substr($search,1)), - intval(local_channel()) - ); - if($r) { - $_GET['cid'] = $r[0]['abook_id']; - $search = $_GET['search'] = ''; - } - } - elseif(strpos($search,'#') === 0) { + if(strpos($search,'#') === 0) { $hashtags = substr($search,1); $search = $_GET['search'] = ''; } @@ -143,7 +132,7 @@ class Network extends \Zotlabs\Web\Controller { $deftag = ''; - if(x($_GET,'search') || $file || (!$pf && $cid)) + if(x($_GET,'search') || $file || (!$pf && $cid) || $hashtags || $verb || $category) $nouveau = true; if($cid) { @@ -169,9 +158,9 @@ class Network extends \Zotlabs\Web\Controller { if(! $update) { // search terms header - if($search) { + if($search || $hashtags) { $o .= replace_macros(get_markup_template("section_title.tpl"),array( - '$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT,'UTF-8') + '$title' => t('Search Results For:') . ' ' . (($search) ? htmlspecialchars($search, ENT_COMPAT,'UTF-8') : '#' . htmlspecialchars($hashtags, ENT_COMPAT,'UTF-8')) )); } -- cgit v1.2.3 From cc9ca8bbffaceb7273b4999e538a3d211ae3cf09 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 29 Sep 2018 18:38:19 +0200 Subject: do not unset $_GET[search] and adjust activity_order widget --- Zotlabs/Module/Network.php | 2 +- Zotlabs/Widget/Activity_order.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 73f09f90b..21507752d 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -86,7 +86,7 @@ class Network extends \Zotlabs\Web\Controller { if($search) { if(strpos($search,'#') === 0) { $hashtags = substr($search,1); - $search = $_GET['search'] = ''; + $search = ''; } } diff --git a/Zotlabs/Widget/Activity_order.php b/Zotlabs/Widget/Activity_order.php index 2dceee70e..d9dbcc91f 100644 --- a/Zotlabs/Widget/Activity_order.php +++ b/Zotlabs/Widget/Activity_order.php @@ -55,7 +55,7 @@ class Activity_order { } // override order for search, filer and cid results - if(x($_GET,'search') || x($_GET,'file') || (! x($_GET,'pf') && x($_GET,'cid'))) { + if(x($_GET,'search') || x($_GET,'file') || (! x($_GET,'pf') && x($_GET,'cid')) || x($_GET,'verb') || x($_GET,'tag') || x($_GET,'cat')) { $unthreaded_active = 'active'; $commentord_active = $postord_active = 'disabled'; } -- cgit v1.2.3 From ff20370d0bd8c08942c062ab105bc839969a3902 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Sat, 29 Sep 2018 20:22:27 +0200 Subject: Status editor hook --- Zotlabs/Module/Article_edit.php | 2 +- Zotlabs/Module/Articles.php | 2 +- Zotlabs/Module/Blocks.php | 2 +- Zotlabs/Module/Card_edit.php | 2 +- Zotlabs/Module/Cards.php | 2 +- Zotlabs/Module/Channel.php | 2 +- Zotlabs/Module/Display.php | 2 +- Zotlabs/Module/Editblock.php | 2 +- Zotlabs/Module/Editlayout.php | 2 +- Zotlabs/Module/Editpost.php | 2 +- Zotlabs/Module/Editwebpage.php | 2 +- Zotlabs/Module/Hq.php | 2 +- Zotlabs/Module/Layouts.php | 2 +- Zotlabs/Module/Network.php | 2 +- Zotlabs/Module/Pubstream.php | 2 +- Zotlabs/Module/Rpost.php | 2 +- Zotlabs/Module/Webpages.php | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Article_edit.php b/Zotlabs/Module/Article_edit.php index 89abccc40..d3cce343f 100644 --- a/Zotlabs/Module/Article_edit.php +++ b/Zotlabs/Module/Article_edit.php @@ -122,7 +122,7 @@ class Article_edit extends \Zotlabs\Web\Controller { 'bbcode' => (($mimetype == 'text/bbcode') ? true : false) ); - $editor = status_editor($a, $x); + $editor = status_editor($a, $x, false, 'Article_edit'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Article'), diff --git a/Zotlabs/Module/Articles.php b/Zotlabs/Module/Articles.php index ad4d67c4e..58c16be45 100644 --- a/Zotlabs/Module/Articles.php +++ b/Zotlabs/Module/Articles.php @@ -132,7 +132,7 @@ class Articles extends Controller { $x['title'] = $_REQUEST['title']; if($_REQUEST['body']) $x['body'] = $_REQUEST['body']; - $editor = status_editor($a,$x); + $editor = status_editor($a,$x,false,'Articles'); } else { diff --git a/Zotlabs/Module/Blocks.php b/Zotlabs/Module/Blocks.php index e6a97794d..fde30a6dd 100644 --- a/Zotlabs/Module/Blocks.php +++ b/Zotlabs/Module/Blocks.php @@ -109,7 +109,7 @@ class Blocks extends \Zotlabs\Web\Controller { if($_REQUEST['pagetitle']) $x['pagetitle'] = $_REQUEST['pagetitle']; - $editor = status_editor($a,$x); + $editor = status_editor($a,$x,false,'Blocks'); $r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig diff --git a/Zotlabs/Module/Card_edit.php b/Zotlabs/Module/Card_edit.php index 694bdc4ea..e01e70fdb 100644 --- a/Zotlabs/Module/Card_edit.php +++ b/Zotlabs/Module/Card_edit.php @@ -122,7 +122,7 @@ class Card_edit extends \Zotlabs\Web\Controller { 'bbcode' => (($mimetype == 'text/bbcode') ? true : false) ); - $editor = status_editor($a, $x); + $editor = status_editor($a, $x, false, 'Card_edit'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Card'), diff --git a/Zotlabs/Module/Cards.php b/Zotlabs/Module/Cards.php index 3656860a5..b66de158b 100644 --- a/Zotlabs/Module/Cards.php +++ b/Zotlabs/Module/Cards.php @@ -133,7 +133,7 @@ class Cards extends Controller { if($_REQUEST['body']) $x['body'] = $_REQUEST['body']; - $editor = status_editor($a, $x); + $editor = status_editor($a, $x, false, 'Cards'); } else { $editor = ''; diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 74fdc1cb4..8b2e35709 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -168,7 +168,7 @@ class Channel extends Controller { 'reset' => t('Reset form') ); - $o .= status_editor($a,$x); + $o .= status_editor($a,$x,false,'Channel'); } } diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index 1d21b64ac..8b46ebb79 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -81,7 +81,7 @@ class Display extends \Zotlabs\Web\Controller { ); $o = '
'; - $o .= status_editor($a,$x); + $o .= status_editor($a,$x,false,'Display'); $o .= '
'; } diff --git a/Zotlabs/Module/Editblock.php b/Zotlabs/Module/Editblock.php index 563ad9ca2..c031f32a1 100644 --- a/Zotlabs/Module/Editblock.php +++ b/Zotlabs/Module/Editblock.php @@ -132,7 +132,7 @@ class Editblock extends \Zotlabs\Web\Controller { 'bbcode' => (($mimetype == 'text/bbcode') ? true : false) ); - $editor = status_editor($a, $x); + $editor = status_editor($a, $x, false, 'Editblock'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Block'), diff --git a/Zotlabs/Module/Editlayout.php b/Zotlabs/Module/Editlayout.php index 67e0bcd32..50096f1a1 100644 --- a/Zotlabs/Module/Editlayout.php +++ b/Zotlabs/Module/Editlayout.php @@ -131,7 +131,7 @@ class Editlayout extends \Zotlabs\Web\Controller { 'profile_uid' => intval($owner), ); - $editor = status_editor($a, $x); + $editor = status_editor($a, $x, false, 'Editlayout'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Layout'), diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php index 45d8e7644..1c9068e07 100644 --- a/Zotlabs/Module/Editpost.php +++ b/Zotlabs/Module/Editpost.php @@ -102,7 +102,7 @@ class Editpost extends \Zotlabs\Web\Controller { 'bbcode' => true ); - $editor = status_editor($a, $x); + $editor = status_editor($a, $x, false, 'Editpost'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit post'), diff --git a/Zotlabs/Module/Editwebpage.php b/Zotlabs/Module/Editwebpage.php index b67421cd5..785eeb4ec 100644 --- a/Zotlabs/Module/Editwebpage.php +++ b/Zotlabs/Module/Editwebpage.php @@ -160,7 +160,7 @@ class Editwebpage extends \Zotlabs\Web\Controller { 'bbcode' => (($mimetype == 'text/bbcode') ? true : false) ); - $editor = status_editor($a, $x); + $editor = status_editor($a, $x, false, 'Editwebpage'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit Webpage'), diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index fee4246c0..3535ac71a 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -138,7 +138,7 @@ class Hq extends \Zotlabs\Web\Controller { [ '$no_messages' => (($target_item) ? false : true), '$no_messages_label' => [ t('Welcome to Hubzilla!'), t('You have got no unseen posts...') ], - '$editor' => status_editor($a,$x) + '$editor' => status_editor($a,$x,false,'Hq') ] ); diff --git a/Zotlabs/Module/Layouts.php b/Zotlabs/Module/Layouts.php index 19efb37fd..25e27d226 100644 --- a/Zotlabs/Module/Layouts.php +++ b/Zotlabs/Module/Layouts.php @@ -141,7 +141,7 @@ class Layouts extends \Zotlabs\Web\Controller { if($_REQUEST['pagetitle']) $x['pagetitle'] = $_REQUEST['pagetitle']; - $editor = status_editor($a,$x); + $editor = status_editor($a,$x,false,'Layouts'); $r = q("select iconfig.iid, iconfig.v, mid, title, body, mimetype, created, edited, item_type from iconfig left join item on iconfig.iid = item.id diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 21507752d..919996943 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -196,7 +196,7 @@ class Network extends \Zotlabs\Web\Controller { $x['pretext'] = $deftag; - $status_editor = status_editor($a,$x); + $status_editor = status_editor($a,$x,false,'Network'); $o .= $status_editor; $static = channel_manual_conv_update(local_channel()); diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 7b80a3978..19cb72b5b 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -81,7 +81,7 @@ class Pubstream extends \Zotlabs\Web\Controller { ); $o = '
'; - $o .= status_editor($a,$x); + $o .= status_editor($a,$x,false,'Pubstream'); $o .= '
'; } diff --git a/Zotlabs/Module/Rpost.php b/Zotlabs/Module/Rpost.php index 86ee296ec..f03dae2bf 100644 --- a/Zotlabs/Module/Rpost.php +++ b/Zotlabs/Module/Rpost.php @@ -138,7 +138,7 @@ class Rpost extends \Zotlabs\Web\Controller { 'jotnets' => true ); - $editor = status_editor($a,$x); + $editor = status_editor($a,$x,false,'Rpost'); $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit post'), diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index c9b2264bf..787ed5850 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -208,7 +208,7 @@ class Webpages extends Controller { if(! $r) $x['pagetitle'] = 'home'; - $editor = status_editor($a,$x); + $editor = status_editor($a,$x,false,'Webpages'); $pages = null; -- cgit v1.2.3 From 7dadf387e58ade457698dc2ffc58bbda7be46652 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 1 Oct 2018 11:01:56 +0200 Subject: indicate locked features --- Zotlabs/Module/Settings/Directory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Directory.php b/Zotlabs/Module/Settings/Directory.php index 2682bcafc..6e24a2cfa 100644 --- a/Zotlabs/Module/Settings/Directory.php +++ b/Zotlabs/Module/Settings/Directory.php @@ -6,7 +6,7 @@ namespace Zotlabs\Module\Settings; class Directory { function post() { - + $module = substr(strrchr(strtolower(static::class), '\\'), 1); check_form_security_token_redirectOnErr('/settings/' . $module, 'settings_' . $module); -- cgit v1.2.3 From 08a287dea10321a60473c8fd684a320ef94bdd37 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 1 Oct 2018 12:38:04 +0200 Subject: do not default to channel_startpage if startpage app is not installed --- Zotlabs/Module/Home.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Home.php b/Zotlabs/Module/Home.php index 647a6412a..7f2d6424d 100644 --- a/Zotlabs/Module/Home.php +++ b/Zotlabs/Module/Home.php @@ -13,14 +13,12 @@ class Home extends \Zotlabs\Web\Controller { $ret = array(); call_hooks('home_init',$ret); - + $splash = ((argc() > 1 && argv(1) === 'splash') ? true : false); $channel = \App::get_channel(); if(local_channel() && $channel && $channel['xchan_url'] && ! $splash) { - $dest = $channel['channel_startpage']; - if(! $dest) - $dest = get_pconfig(local_channel(),'system','startpage'); + $dest = (($ret['startpage']) ? $ret['startpage'] : ''); if(! $dest) $dest = get_config('system','startpage'); if(! $dest) -- cgit v1.2.3 From 72abe5f3d377043f6aba31090a6671a7e171ddfb Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 1 Oct 2018 12:47:14 +0200 Subject: do not rely on startpage pconfig anymore --- Zotlabs/Widget/Notifications.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Notifications.php b/Zotlabs/Widget/Notifications.php index a4cf4e706..0f9f609e4 100644 --- a/Zotlabs/Widget/Notifications.php +++ b/Zotlabs/Widget/Notifications.php @@ -160,7 +160,7 @@ class Notifications { '$notifications' => $notifications, '$no_notifications' => t('Sorry, you have got no notifications at the moment'), '$loading' => t('Loading'), - '$startpage' => get_pconfig(local_channel(), 'system', 'startpage') + '$startpage' => $channel['channel_startpage'] )); return $o; -- cgit v1.2.3 From 67f19745fd5c66345a7e64b3d5fdedf6c1a6b8b6 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 2 Oct 2018 14:29:56 +0200 Subject: add app_destroy hook which allows addons to perform post delete actions --- Zotlabs/Lib/Apps.php | 1 + 1 file changed, 1 insertion(+) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index c54a5a111..ec1f3f9dc 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -623,6 +623,7 @@ class Apps { intval(TERM_OBJ_APP), intval($x[0]['id']) ); + call_hooks('app_destroy', $x[0]); } else { $r = q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d", -- cgit v1.2.3 From d33c331abd3ae500fc7cdac206ea647c4c71905e Mon Sep 17 00:00:00 2001 From: zotlabs Date: Wed, 3 Oct 2018 21:18:23 -0700 Subject: regression: double linebreaks in viewsrc output --- Zotlabs/Module/Viewsrc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Viewsrc.php b/Zotlabs/Module/Viewsrc.php index 5900e385a..119990b57 100644 --- a/Zotlabs/Module/Viewsrc.php +++ b/Zotlabs/Module/Viewsrc.php @@ -47,7 +47,7 @@ class Viewsrc extends \Zotlabs\Web\Controller { $content = escape_tags($r[0]['body']); - $o = (($json) ? json_encode($content) : str_replace("\n",'
',$content)); + $o = (($json) ? json_encode($content) : $content); } } -- cgit v1.2.3 From d0605e8d5f7c666fffc01352de4d9ed4738f41ab Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 4 Oct 2018 11:50:38 +0200 Subject: uexport app --- Zotlabs/Module/Uexport.php | 21 ++++++++++++++++++--- Zotlabs/Widget/Settings_menu.php | 7 ------- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Uexport.php b/Zotlabs/Module/Uexport.php index 9af1887dc..3d1587b87 100644 --- a/Zotlabs/Module/Uexport.php +++ b/Zotlabs/Module/Uexport.php @@ -1,18 +1,24 @@ 1) { $sections = (($_REQUEST['sections']) ? explode(',',$_REQUEST['sections']) : ''); - $channel = \App::get_channel(); + $channel = App::get_channel(); if(argc() > 1 && intval(argv(1)) > 1900) { $year = intval(argv(1)); @@ -47,6 +53,15 @@ class Uexport extends \Zotlabs\Web\Controller { } function get() { + + if(! Apps::system_app_installed(local_channel(), 'Channel Export')) { + //Do not display any associated widgets at this point + App::$pdl = ''; + + $o = '' . t('Channel Export App') . ' (' . t('Not Installed') . '):
'; + $o .= t('Export your channel'); + return $o; + } $y = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index 238b8071e..194c4b05b 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -9,7 +9,6 @@ class Settings_menu { if(! local_channel()) return; - $channel = \App::get_channel(); $abook_self_id = 0; @@ -66,12 +65,6 @@ class Settings_menu { ); } - $tabs[] = array( - 'label' => t('Export channel'), - 'url' => z_root() . '/uexport', - 'selected' => '' - ); - if($role === false || $role === 'custom') { $tabs[] = array( 'label' => t('Connection Default Permissions'), -- cgit v1.2.3 From c00dc6120d5a458a2386ab4e561437d9f8c62b3c Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 4 Oct 2018 13:26:45 +0200 Subject: defperm app --- Zotlabs/Lib/Apps.php | 8 +++++++ Zotlabs/Module/Defperms.php | 46 +++++++++++++++++++++++++++------------- Zotlabs/Widget/Settings_menu.php | 8 ------- 3 files changed, 39 insertions(+), 23 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index ec1f3f9dc..8db4e000f 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -271,6 +271,10 @@ class Apps { if(! can_view_public_stream()) unset($ret); break; + case 'custom_role': + if(get_pconfig(local_channel(),'system','permissions_role') != 'custom') + unset($ret); + break; case 'observer': if(! $observer) unset($ret); @@ -468,6 +472,10 @@ class Apps { if(! can_view_public_stream()) return ''; break; + case 'custom_role': + if(get_pconfig(local_channel(),'system','permissions_role') != 'custom') + return ''; + break; case 'observer': $observer = \App::get_observer(); if(! $observer) diff --git a/Zotlabs/Module/Defperms.php b/Zotlabs/Module/Defperms.php index 2e886aa64..463ecb57a 100644 --- a/Zotlabs/Module/Defperms.php +++ b/Zotlabs/Module/Defperms.php @@ -1,15 +1,16 @@ ' . t('Default Permissions App') . ' (' . t('Not Installed') . '):
'; + $o .= t('Set custom default permissions for new connections'); + return $o; + } $section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : ''); - $channel = \App::get_channel(); + $channel = App::get_channel(); $yes_no = array(t('No'),t('Yes')); @@ -194,7 +210,7 @@ class Defperms extends \Zotlabs\Web\Controller { } $o .= " }\n\n"; - if(\App::$poi) { + if(App::$poi) { $sections = []; @@ -204,9 +220,9 @@ class Defperms extends \Zotlabs\Web\Controller { $perms = array(); - $channel = \App::get_channel(); + $channel = App::get_channel(); - $contact = \App::$poi; + $contact = App::$poi; $global_perms = \Zotlabs\Access\Permissions::Perms(); diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index 194c4b05b..a4b288441 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -65,14 +65,6 @@ class Settings_menu { ); } - if($role === false || $role === 'custom') { - $tabs[] = array( - 'label' => t('Connection Default Permissions'), - 'url' => z_root() . '/defperms', - 'selected' => '' - ); - } - $tabtpl = get_markup_template("generic_links_widget.tpl"); return replace_macros($tabtpl, array( '$title' => t('Settings'), -- cgit v1.2.3 From cccea911fa6a8dadb8fae03676ac933b2ed9592a Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 4 Oct 2018 13:44:26 +0200 Subject: remove redundant var --- Zotlabs/Widget/Settings_menu.php | 2 -- 1 file changed, 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index a4b288441..c537c3835 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -15,8 +15,6 @@ class Settings_menu { // Retrieve the 'self' address book entry for use in the auto-permissions link - $role = get_pconfig(local_channel(),'system','permissions_role'); - $abk = q("select abook_id from abook where abook_channel = %d and abook_self = 1 limit 1", intval(local_channel()) ); -- cgit v1.2.3 From 6e03104e3ee785954b4f755240d1595f702522b2 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 4 Oct 2018 20:48:22 +0200 Subject: move *_list_mode to features --- Zotlabs/Module/Channel.php | 2 +- Zotlabs/Module/Network.php | 2 +- Zotlabs/Module/Settings/Display.php | 6 ------ 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 8b2e35709..f1537ed15 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -182,7 +182,7 @@ class Channel extends Controller { $item_normal_update = item_normal_update(); $sql_extra = item_permissions_sql(App::$profile['profile_uid']); - if(get_pconfig(App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid)) + if(feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (! $mid)) $page_mode = 'list'; else $page_mode = 'client'; diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 919996943..015351cbf 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -437,7 +437,7 @@ class Network extends \Zotlabs\Web\Controller { $abook_uids = " and abook.abook_channel = " . local_channel() . " "; $uids = " and item.uid = " . local_channel() . " "; - if(get_pconfig(local_channel(),'system','network_list_mode')) + if(feature_enabled(local_channel(), 'network_list_mode')) $page_mode = 'list'; else $page_mode = 'client'; diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php index 0c63a3056..b4f8928e0 100644 --- a/Zotlabs/Module/Settings/Display.php +++ b/Zotlabs/Module/Settings/Display.php @@ -27,8 +27,6 @@ class Display { $user_scalable = ((x($_POST,'user_scalable')) ? intval($_POST['user_scalable']) : 0); $nosmile = ((x($_POST,'nosmile')) ? intval($_POST['nosmile']) : 0); $title_tosource = ((x($_POST,'title_tosource')) ? intval($_POST['title_tosource']) : 0); - $channel_list_mode = ((x($_POST,'channel_list_mode')) ? intval($_POST['channel_list_mode']) : 0); - $network_list_mode = ((x($_POST,'network_list_mode')) ? intval($_POST['network_list_mode']) : 0); $manual_update = ((array_key_exists('manual_update',$_POST)) ? intval($_POST['manual_update']) : 0); $start_menu = ((x($_POST,'start_menu')) ? intval($_POST['start_menu']) : 0); @@ -55,8 +53,6 @@ class Display { set_pconfig(local_channel(),'system','itemspage', $itemspage); set_pconfig(local_channel(),'system','no_smilies',1-intval($nosmile)); set_pconfig(local_channel(),'system','title_tosource',$title_tosource); - set_pconfig(local_channel(),'system','channel_list_mode', $channel_list_mode); - set_pconfig(local_channel(),'system','network_list_mode', $network_list_mode); set_pconfig(local_channel(),'system','channel_divmore_height', $channel_divmore_height); set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height); set_pconfig(local_channel(),'system','manual_conversation_update', $manual_update); @@ -215,8 +211,6 @@ class Display { '$manual_update' => array('manual_update', t('Manual conversation updates'), channel_manual_conv_update(local_channel()), t('Default is on, turning this off may increase screen jumping'), $yes_no), '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no), '$theme_config' => $theme_config, - '$channel_list_mode' => array('channel_list_mode', t('Use blog/list mode on channel page'), get_pconfig(local_channel(),'system','channel_list_mode'), t('(comments displayed separately)'), $yes_no), - '$network_list_mode' => array('network_list_mode', t('Use blog/list mode on grid page'), get_pconfig(local_channel(),'system','network_list_mode'), t('(comments displayed separately)'), $yes_no), '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')), '$network_divmore_height' => array('network_divmore_height', t('Grid page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')), '$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no] -- cgit v1.2.3 From d4af745fc8000be9fcc198d3d0205a6b134e374c Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 4 Oct 2018 21:38:39 +0200 Subject: move *_divmore_height setting to the module extra_settings, and fix issue where feature settings were not synced if rpath was provided --- Zotlabs/Module/Settings/Calendar.php | 4 ++++ Zotlabs/Module/Settings/Channel_home.php | 25 +++++++++++++++++++++++++ Zotlabs/Module/Settings/Connections.php | 4 ++++ Zotlabs/Module/Settings/Directory.php | 4 ++++ Zotlabs/Module/Settings/Display.php | 11 ----------- Zotlabs/Module/Settings/Editor.php | 4 ++++ Zotlabs/Module/Settings/Events.php | 4 ++++ Zotlabs/Module/Settings/Manage.php | 4 ++++ Zotlabs/Module/Settings/Network.php | 28 ++++++++++++++++++++++++++-- Zotlabs/Module/Settings/Photos.php | 4 ++++ Zotlabs/Module/Settings/Profiles.php | 4 ++++ 11 files changed, 83 insertions(+), 13 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Calendar.php b/Zotlabs/Module/Settings/Calendar.php index b3a611cdf..a27bf0fa5 100644 --- a/Zotlabs/Module/Settings/Calendar.php +++ b/Zotlabs/Module/Settings/Calendar.php @@ -16,6 +16,10 @@ class Calendar { process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } diff --git a/Zotlabs/Module/Settings/Channel_home.php b/Zotlabs/Module/Settings/Channel_home.php index 1d1cc370b..23c7ee1ab 100644 --- a/Zotlabs/Module/Settings/Channel_home.php +++ b/Zotlabs/Module/Settings/Channel_home.php @@ -14,8 +14,18 @@ class Channel_home { $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); + + $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400); + if($channel_divmore_height < 50) + $channel_divmore_height = 50; + + set_pconfig(local_channel(),'system','channel_divmore_height', $channel_divmore_height); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } @@ -26,6 +36,20 @@ class Channel_home { $features = get_module_features($module); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); + $channel_divmore_height = [ + 'channel_divmore_height', + t('Max height of content (in pixels)'), + ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), + t('Click to expand content exceeding this height') + ]; + + $extra_settings_html = replace_macros(get_markup_template('field_input.tpl'), + [ + '$field' => $channel_divmore_height + ] + ); + + $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( @@ -34,6 +58,7 @@ class Channel_home { '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Channel Home Settings'), '$features' => process_module_features_get(local_channel(), $features), + '$extra_settings_html' => $extra_settings_html, '$submit' => t('Submit') )); diff --git a/Zotlabs/Module/Settings/Connections.php b/Zotlabs/Module/Settings/Connections.php index 70b4daa42..cac357791 100644 --- a/Zotlabs/Module/Settings/Connections.php +++ b/Zotlabs/Module/Settings/Connections.php @@ -16,6 +16,10 @@ class Connections { process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } diff --git a/Zotlabs/Module/Settings/Directory.php b/Zotlabs/Module/Settings/Directory.php index 6e24a2cfa..13fe6eb79 100644 --- a/Zotlabs/Module/Settings/Directory.php +++ b/Zotlabs/Module/Settings/Directory.php @@ -16,6 +16,10 @@ class Directory { process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } diff --git a/Zotlabs/Module/Settings/Display.php b/Zotlabs/Module/Settings/Display.php index b4f8928e0..45d80e011 100644 --- a/Zotlabs/Module/Settings/Display.php +++ b/Zotlabs/Module/Settings/Display.php @@ -30,13 +30,6 @@ class Display { $manual_update = ((array_key_exists('manual_update',$_POST)) ? intval($_POST['manual_update']) : 0); $start_menu = ((x($_POST,'start_menu')) ? intval($_POST['start_menu']) : 0); - $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400); - if($channel_divmore_height < 50) - $channel_divmore_height = 50; - $network_divmore_height = ((x($_POST,'network_divmore_height')) ? intval($_POST['network_divmore_height']) : 400); - if($network_divmore_height < 50) - $network_divmore_height = 50; - $browser_update = ((x($_POST,'browser_update')) ? intval($_POST['browser_update']) : 0); $browser_update = $browser_update * 1000; if($browser_update < 10000) @@ -53,8 +46,6 @@ class Display { set_pconfig(local_channel(),'system','itemspage', $itemspage); set_pconfig(local_channel(),'system','no_smilies',1-intval($nosmile)); set_pconfig(local_channel(),'system','title_tosource',$title_tosource); - set_pconfig(local_channel(),'system','channel_divmore_height', $channel_divmore_height); - set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height); set_pconfig(local_channel(),'system','manual_conversation_update', $manual_update); set_pconfig(local_channel(),'system','channel_menu', $channel_menu); set_pconfig(local_channel(),'system','start_menu', $start_menu); @@ -211,8 +202,6 @@ class Display { '$manual_update' => array('manual_update', t('Manual conversation updates'), channel_manual_conv_update(local_channel()), t('Default is on, turning this off may increase screen jumping'), $yes_no), '$title_tosource' => array('title_tosource', t("Link post titles to source"), $title_tosource, '', $yes_no), '$theme_config' => $theme_config, - '$channel_divmore_height' => array('channel_divmore_height', t('Channel page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','channel_divmore_height')) ? get_pconfig(local_channel(),'system','channel_divmore_height') : 400), t('click to expand content exceeding this height')), - '$network_divmore_height' => array('network_divmore_height', t('Grid page max height of content (in pixels)'), ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400) , t('click to expand content exceeding this height')), '$start_menu' => ['start_menu', t('New Member Links'), $start_menu, t('Display new member quick links menu'), $yes_no] )); diff --git a/Zotlabs/Module/Settings/Editor.php b/Zotlabs/Module/Settings/Editor.php index 93e3ce602..5e7a9473a 100644 --- a/Zotlabs/Module/Settings/Editor.php +++ b/Zotlabs/Module/Settings/Editor.php @@ -16,6 +16,10 @@ class Editor { process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } diff --git a/Zotlabs/Module/Settings/Events.php b/Zotlabs/Module/Settings/Events.php index fcb4441e1..eb6dda99b 100644 --- a/Zotlabs/Module/Settings/Events.php +++ b/Zotlabs/Module/Settings/Events.php @@ -16,6 +16,10 @@ class Events { process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } diff --git a/Zotlabs/Module/Settings/Manage.php b/Zotlabs/Module/Settings/Manage.php index 15d3216e9..9bae12022 100644 --- a/Zotlabs/Module/Settings/Manage.php +++ b/Zotlabs/Module/Settings/Manage.php @@ -16,6 +16,10 @@ class Manage { process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index c51b780f1..aaafe9255 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -14,8 +14,18 @@ class Network { $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); + + $network_divmore_height = ((x($_POST,'network_divmore_height')) ? intval($_POST['network_divmore_height']) : 400); + if($network_divmore_height < 50) + $network_divmore_height = 50; + + set_pconfig(local_channel(),'system','network_divmore_height', $network_divmore_height); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } @@ -26,6 +36,19 @@ class Network { $features = get_module_features($module); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); + $network_divmore_height = [ + 'network_divmore_height', + t('Max height of content (in pixels)'), + ((get_pconfig(local_channel(),'system','network_divmore_height')) ? get_pconfig(local_channel(),'system','network_divmore_height') : 400), + t('Click to expand content exceeding this height') + ]; + + $extra_settings_html = replace_macros(get_markup_template('field_input.tpl'), + [ + '$field' => $network_divmore_height + ] + ); + $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( @@ -33,8 +56,9 @@ class Network { '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Activity Settings'), - '$features' => process_module_features_get(local_channel(), $features), - '$submit' => t('Submit') + '$features' => process_module_features_get(local_channel(), $features), + '$extra_settings_html' => $extra_settings_html, + '$submit' => t('Submit') )); return $o; diff --git a/Zotlabs/Module/Settings/Photos.php b/Zotlabs/Module/Settings/Photos.php index f403b4d38..9edbaa929 100644 --- a/Zotlabs/Module/Settings/Photos.php +++ b/Zotlabs/Module/Settings/Photos.php @@ -16,6 +16,10 @@ class Photos { process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php index 78dc0160e..2dc037317 100644 --- a/Zotlabs/Module/Settings/Profiles.php +++ b/Zotlabs/Module/Settings/Profiles.php @@ -16,6 +16,10 @@ class Profiles { process_module_features_post(local_channel(), $features, $_POST); build_sync_packet(); + + if($_POST['rpath']) + goaway($_POST['rpath']); + return; } -- cgit v1.2.3 From 363fc5c72b9e9564196375137b89e3270774f471 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 4 Oct 2018 21:49:00 +0200 Subject: whitespace --- Zotlabs/Module/Settings/Channel_home.php | 1 - 1 file changed, 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Channel_home.php b/Zotlabs/Module/Settings/Channel_home.php index 23c7ee1ab..0e916d530 100644 --- a/Zotlabs/Module/Settings/Channel_home.php +++ b/Zotlabs/Module/Settings/Channel_home.php @@ -49,7 +49,6 @@ class Channel_home { ] ); - $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( -- cgit v1.2.3 From 9fe9137c9689347e2be1d6bf6633956e147e368c Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 4 Oct 2018 22:01:34 +0200 Subject: fix displaying of perm cats selector --- Zotlabs/Module/Settings/Channel.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index c473a70a4..6b49f165d 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module\Settings; +use Zotlabs\Lib\Apps; + require_once('include/selectors.php'); @@ -551,8 +553,8 @@ class Channel { '$suggestme' => $suggestme, '$group_select' => $group_select, '$role' => array('permissions_role' , t('Channel role and privacy'), $permissions_role, '', $perm_roles), - '$defpermcat' => [ 'defpermcat', t('Default Permissions Group'), $default_permcat, '', $permcats ], - '$permcat_enable' => feature_enabled(local_channel(),'permcats'), + '$defpermcat' => [ 'defpermcat', t('Default permissions category'), $default_permcat, '', $permcats ], + '$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'), '$profile_in_dir' => $profile_in_dir, '$hide_friends' => $hide_friends, '$hide_wall' => $hide_wall, -- cgit v1.2.3 From 1eaf6df842184743ee20ec69931be1ff7136f34e Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 4 Oct 2018 22:21:20 +0200 Subject: fix issues with bs accordions --- Zotlabs/Module/Permcats.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Permcats.php b/Zotlabs/Module/Permcats.php index 262a14fe4..75ac2ac87 100644 --- a/Zotlabs/Module/Permcats.php +++ b/Zotlabs/Module/Permcats.php @@ -25,7 +25,7 @@ class Permcats extends Controller { $name = escape_tags(trim($_POST['name'])); if(! $name) { - notice( t('Permission Name is required.') . EOL); + notice( t('Permission category name is required.') . EOL); return; } @@ -117,7 +117,7 @@ class Permcats extends Controller { '$atoken' => $atoken, '$url1' => z_root() . '/channel/' . $channel['channel_address'], '$url2' => z_root() . '/photos/' . $channel['channel_address'], - '$name' => array('name', t('Permission Name') . ' *', (($name) ? $name : ''), ''), + '$name' => array('name', t('Permission category name') . ' *', (($name) ? $name : ''), ''), '$me' => t('My Settings'), '$perms' => $perms, '$inherited' => t('inherited'), -- cgit v1.2.3 From 59bd90b967e9938c294a3a2738e8d177fa497782 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Fri, 5 Oct 2018 13:31:54 +0200 Subject: Add 'Channel Export' in Apps list --- Zotlabs/Lib/Apps.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 8db4e000f..826b2db29 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -354,7 +354,8 @@ class Apps { 'Permission Categories' => t('Permission Categories'), 'Premium Channel' => t('Premium Channel'), 'Public Stream' => t('Public Stream'), - 'My Chatrooms' => t('My Chatrooms') + 'My Chatrooms' => t('My Chatrooms'), + 'Channel Export' => t('Channel Export') ); if(array_key_exists('name',$arr)) { -- cgit v1.2.3 From d39ebebc9df1c4f85e5ce01f512469848cd64be7 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Fri, 5 Oct 2018 13:25:16 -0400 Subject: Fix: hooks not added to App::[] at the time of registration --- Zotlabs/Extend/Hook.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Extend/Hook.php b/Zotlabs/Extend/Hook.php index 81260ead6..5a1fe6686 100644 --- a/Zotlabs/Extend/Hook.php +++ b/Zotlabs/Extend/Hook.php @@ -42,6 +42,7 @@ class Hook { intval($version) ); + self::insert($hook, $function, $version, $priority); return $r; } @@ -119,4 +120,4 @@ class Hook { App::$hooks[$hook][] = array('', $fn, $priority, $version); } -} \ No newline at end of file +} -- cgit v1.2.3 From 1922a2139d036bec32a69e7ac250b6307ae186ea Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Fri, 5 Oct 2018 19:30:49 +0200 Subject: Revert "Merge branch 'dev' into 'dev'" This reverts merge request !1310 --- Zotlabs/Extend/Hook.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Extend/Hook.php b/Zotlabs/Extend/Hook.php index 5a1fe6686..81260ead6 100644 --- a/Zotlabs/Extend/Hook.php +++ b/Zotlabs/Extend/Hook.php @@ -42,7 +42,6 @@ class Hook { intval($version) ); - self::insert($hook, $function, $version, $priority); return $r; } @@ -120,4 +119,4 @@ class Hook { App::$hooks[$hook][] = array('', $fn, $priority, $version); } -} +} \ No newline at end of file -- cgit v1.2.3 From 835e222af0df627a262ab55e940f9d3808b6e000 Mon Sep 17 00:00:00 2001 From: zotlabs Date: Fri, 5 Oct 2018 16:27:50 -0700 Subject: minor app cleanup --- Zotlabs/Lib/Apps.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 8db4e000f..7f4bd6ef9 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -272,7 +272,7 @@ class Apps { unset($ret); break; case 'custom_role': - if(get_pconfig(local_channel(),'system','permissions_role') != 'custom') + if(get_pconfig(local_channel(),'system','permissions_role') !== 'custom') unset($ret); break; case 'observer': @@ -535,8 +535,8 @@ class Apps { '$installed' => $installed, '$action_label' => (($hosturl && in_array($mode, ['view','install'])) ? $install_action : ''), '$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''), - '$delete' => ((local_channel() && $mode == 'edit') ? t('Delete') : ''), - '$undelete' => ((local_channel() && $mode == 'edit') ? t('Undelete') : ''), + '$delete' => ((local_channel() && $installed && $mode == 'edit') ? t('Delete') : ''), + '$undelete' => ((local_channel() && $installed && $mode == 'edit') ? t('Undelete') : ''), '$settings_url' => ((local_channel() && $installed && $mode == 'list') ? $papp['settings_url'] : ''), '$deleted' => $papp['deleted'], '$feature' => (($papp['embed'] || $mode == 'edit') ? false : true), @@ -985,7 +985,7 @@ class Apps { $arr['author'] = $sys['channel_hash']; } - if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (! strpos($arr['photo'],z_root()))) { + if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (strpos($arr['photo'],z_root()) !== false)) { $x = import_xchan_photo(str_replace('$baseurl',z_root(),$arr['photo']),get_observer_hash(),true); $arr['photo'] = $x[1]; } @@ -1071,7 +1071,7 @@ class Apps { if((! $darray['app_url']) || (! $darray['app_id'])) return $ret; - if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (! strpos($arr['photo'],z_root()))) { + if($arr['photo'] && (strpos($arr['photo'],'icon:') === false) && (strpos($arr['photo'],z_root()) !== false)) { $x = import_xchan_photo(str_replace('$baseurl',z_root(),$arr['photo']),get_observer_hash(),true); $arr['photo'] = $x[1]; } -- cgit v1.2.3 From ebb4811a75d6c5a324b932a56df5e7cd6c068446 Mon Sep 17 00:00:00 2001 From: Max Kostikov Date: Sat, 6 Oct 2018 14:06:24 +0200 Subject: Respect new table names on import --- Zotlabs/Module/Import.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php index c5c52674a..6016328a5 100644 --- a/Zotlabs/Module/Import.php +++ b/Zotlabs/Module/Import.php @@ -426,7 +426,7 @@ class Import extends \Zotlabs\Web\Controller { unset($group['id']); $group['uid'] = $channel['channel_id']; - create_table_from_array('groups', $group); + create_table_from_array('pgrp', $group); } $r = q("select * from pgrp where uid = %d", intval($channel['channel_id']) @@ -448,7 +448,7 @@ class Import extends \Zotlabs\Web\Controller { if($x['old'] == $group_member['gid']) $group_member['gid'] = $x['new']; } - create_table_from_array('group_member', $group_member); + create_table_from_array('pgrp_member', $group_member); } } -- cgit v1.2.3 From c2c891723fc0e56f0c373ca1043cdb548f2ed8ab Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 14:48:12 +0200 Subject: bookmark app --- Zotlabs/Lib/Apps.php | 2 +- Zotlabs/Lib/ThreadItem.php | 4 +++- Zotlabs/Module/Bookmarks.php | 18 ++++++++++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 826b2db29..d7cea6b7c 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -306,7 +306,7 @@ class Apps { 'Cards' => t('Cards'), 'Admin' => t('Site Admin'), 'Report Bug' => t('Report Bug'), - 'View Bookmarks' => t('View Bookmarks'), + 'Bookmarks' => t('Bookmarks'), 'Chatrooms' => t('Chatrooms'), 'Connections' => t('Connections'), 'Remote Diagnostics' => t('Remote Diagnostics'), diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 48018f66c..78714c2c4 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -2,6 +2,8 @@ namespace Zotlabs\Lib; +use Zotlabs\Lib\Apps; + require_once('include/text.php'); /** @@ -272,7 +274,7 @@ class ThreadItem { } $has_bookmarks = false; - if(is_array($item['term'])) { + if(Apps::system_app_installed(local_channel(), 'Bookmarks') && is_array($item['term'])) { foreach($item['term'] as $t) { if(($t['ttype'] == TERM_BOOKMARK)) $has_bookmarks = true; diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php index cee86a47d..1c4c6a513 100644 --- a/Zotlabs/Module/Bookmarks.php +++ b/Zotlabs/Module/Bookmarks.php @@ -1,6 +1,9 @@ ' . t('Bookmarks App') . ' (' . t('Not Installed') . '):
'; + $o .= t('Bookmark links from the item dropdown and manage them'); + return $o; + } require_once('include/menu.php'); require_once('include/conversation.php'); -- cgit v1.2.3 From a522a667157c778fca74ccd3391f1f9fdc84c3cc Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 14:50:17 +0200 Subject: bookmarks: change wording --- Zotlabs/Module/Bookmarks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php index 1c4c6a513..4b4929c65 100644 --- a/Zotlabs/Module/Bookmarks.php +++ b/Zotlabs/Module/Bookmarks.php @@ -76,7 +76,7 @@ class Bookmarks extends \Zotlabs\Web\Controller { App::$pdl = ''; $o = '' . t('Bookmarks App') . ' (' . t('Not Installed') . '):
'; - $o .= t('Bookmark links from the item dropdown and manage them'); + $o .= t('Bookmark links from posts and manage them'); return $o; } -- cgit v1.2.3 From 9850d1842087d1842d9360ed5fd3bdea74e575c9 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 15:00:28 +0200 Subject: gallery is not a core app --- Zotlabs/Lib/Apps.php | 1 - 1 file changed, 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index d7cea6b7c..3c9616375 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -345,7 +345,6 @@ class Apps { 'CalDAV' => t('CalDAV'), 'CardDAV' => t('CardDAV'), 'Channel Sources' => t('Channel Sources'), - 'Gallery' => t('Gallery'), 'Guest Access' => t('Guest Access'), 'Notes' => t('Notes'), 'OAuth Apps Manager' => t('OAuth Apps Manager'), -- cgit v1.2.3 From 453ce4df3bddab898f49102f74ffb072693e2dbd Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 15:12:13 +0200 Subject: admin should not be an app imho - we can not install/delete admin abilities. Remove suggest channels from base apps. --- Zotlabs/Lib/Apps.php | 3 --- 1 file changed, 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 3c9616375..19cc78d17 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -59,7 +59,6 @@ class Apps { static public function get_base_apps() { return get_config('system','base_apps',[ 'Connections', - 'Suggest Channels', 'Grid', 'Settings', 'Files', @@ -75,8 +74,6 @@ class Apps { ]); } - - static public function import_system_apps() { if(! local_channel()) return; -- cgit v1.2.3 From 6a297a8f3d5eb4c403a14799e83de22d0637b46d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 15:21:22 +0200 Subject: remote diagnostics app --- Zotlabs/Module/Probe.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Probe.php b/Zotlabs/Module/Probe.php index 2c67c6aae..d338b08ea 100644 --- a/Zotlabs/Module/Probe.php +++ b/Zotlabs/Module/Probe.php @@ -1,16 +1,29 @@ ' . t('Remote Diagnostics App') . ' (' . t('Not Installed') . '):
'; + $o .= t('Perform diagnostics on remote channels'); + return $o; + } + } + nav_set_selected('Remote Diagnostics'); - $o .= '

Probe Diagnostic

'; + $o .= '

Remote Diagnostics

'; $o .= '
'; $o .= 'Lookup address: '; @@ -19,7 +32,7 @@ class Probe extends \Zotlabs\Web\Controller { $o .= '

'; if(x($_GET,'addr')) { - $channel = \App::get_channel(); + $channel = App::get_channel(); $addr = trim($_GET['addr']); $do_import = ((intval($_GET['import']) && is_site_admin()) ? true : false); -- cgit v1.2.3 From 18726737d0116f13ec83cb2c1094a36d08980b7d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 15:27:46 +0200 Subject: randprof app --- Zotlabs/Module/Randprof.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Randprof.php b/Zotlabs/Module/Randprof.php index 94ec095cb..c38b07ead 100644 --- a/Zotlabs/Module/Randprof.php +++ b/Zotlabs/Module/Randprof.php @@ -1,11 +1,17 @@ ' . t('Random Channel App') . ' (' . t('Not Installed') . '):
'; + $o .= t('Visit a random channel in the $Projectname network'); + return $o; + } + } + + } } -- cgit v1.2.3 From b8991750c5d36714100d20595da6a33149bd7d5d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 16:08:15 +0200 Subject: pubstream app --- Zotlabs/Module/Ping.php | 11 ++++++++--- Zotlabs/Module/Pubstream.php | 14 ++++++++++++++ Zotlabs/Module/Settings/Channel.php | 2 +- Zotlabs/Module/Suggest.php | 21 ++++++++++++++++++--- 4 files changed, 41 insertions(+), 7 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php index baefe62ec..14627f56e 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -2,6 +2,8 @@ namespace Zotlabs\Module; +use Zotlabs\Lib\Apps; + require_once('include/bbcode.php'); /** @@ -147,9 +149,12 @@ class Ping extends \Zotlabs\Web\Controller { if(! ($vnotify & VNOTIFY_LIKE)) $sql_extra = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') "; - $discover_tab_on = can_view_public_stream(); - - $notify_pubs = ((local_channel()) ? ($vnotify & VNOTIFY_PUBS) && $discover_tab_on : $discover_tab_on); + if(local_channel()) { + $notify_pubs = ($vnotify & VNOTIFY_PUBS) && can_view_public_stream() && Apps::system_app_installed(local_channel(), 'Public Stream'); + } + else { + $notify_pubs = can_view_public_stream(); + } if($notify_pubs) { $sys = get_sys_channel(); diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 19cb72b5b..94df29984 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -1,6 +1,9 @@ ' . t('Public Stream App') . ' (' . t('Not Installed') . '):
'; + $o .= t('The unmoderated public stream of this hub'); + return $o; + } + } + if($load) $_SESSION['loadtime'] = datetime_convert(); diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 6b49f165d..ebc444178 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -594,7 +594,7 @@ class Channel { '$vnotify10' => array('vnotify10', t('New connections'), ($vnotify & VNOTIFY_INTRO), VNOTIFY_INTRO, t('Recommended'), $yes_no), '$vnotify11' => ((is_site_admin()) ? array('vnotify11', t('System Registrations'), ($vnotify & VNOTIFY_REGISTER), VNOTIFY_REGISTER, '', $yes_no) : array()), '$vnotify12' => array('vnotify12', t('Unseen shared files'), ($vnotify & VNOTIFY_FILES), VNOTIFY_FILES, '', $yes_no), - '$vnotify13' => (($disable_discover_tab && !$site_firehose) ? array() : array('vnotify13', t('Unseen public activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no)), + '$vnotify13' => ((($disable_discover_tab && !$site_firehose) || !Apps::system_app_installed(local_channel(), 'Public Stream')) ? array() : array('vnotify13', t('Unseen public stream activity'), ($vnotify & VNOTIFY_PUBS), VNOTIFY_PUBS, '', $yes_no)), '$vnotify14' => array('vnotify14', t('Unseen likes and dislikes'), ($vnotify & VNOTIFY_LIKE), VNOTIFY_LIKE, '', $yes_no), '$vnotify15' => array('vnotify15', t('Unseen forum posts'), ($vnotify & VNOTIFY_FORUMS), VNOTIFY_FORUMS, '', $yes_no), '$mailhost' => [ 'mailhost', t('Email notification hub (hostname)'), get_pconfig(local_channel(),'system','email_notify_host',\App::get_hostname()), sprintf( t('If your channel is mirrored to multiple hubs, set this to your preferred location. This will prevent duplicate email notifications. Example: %s'),\App::get_hostname()) ], diff --git a/Zotlabs/Module/Suggest.php b/Zotlabs/Module/Suggest.php index f79e4e245..18961214e 100644 --- a/Zotlabs/Module/Suggest.php +++ b/Zotlabs/Module/Suggest.php @@ -1,15 +1,20 @@ ' . t('Suggest Channels App') . ' (' . t('Not Installed') . '):
'; + $o .= t('Suggestions for channels in the $Projectname network you might be interested in'); + return $o; + } + + $o = ''; + nav_set_selected('Suggest Channels'); $_SESSION['return_url'] = z_root() . '/' . \App::$cmd; -- cgit v1.2.3 From 96277372d55a58349e318e694f4dab3a00fb2f13 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 16:40:30 +0200 Subject: rename grid to network (for consistency) and activity to stream (as seen in osada) because it makes much more sense. --- Zotlabs/Lib/Apps.php | 4 ++-- Zotlabs/Module/Network.php | 2 +- Zotlabs/Module/Settings/Channel.php | 2 +- Zotlabs/Module/Settings/Network.php | 2 +- Zotlabs/Update/_1222.php | 28 ++++++++++++++++++++++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 Zotlabs/Update/_1222.php (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 19cc78d17..5117816bf 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -59,7 +59,7 @@ class Apps { static public function get_base_apps() { return get_config('system','base_apps',[ 'Connections', - 'Grid', + 'Network', 'Settings', 'Files', 'Channel Home', @@ -310,7 +310,7 @@ class Apps { 'Suggest Channels' => t('Suggest Channels'), 'Login' => t('Login'), 'Channel Manager' => t('Channel Manager'), - 'Grid' => t('Activity'), + 'Network' => t('Stream'), 'Settings' => t('Settings'), 'Files' => t('Files'), 'Webpages' => t('Webpages'), diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 015351cbf..792f92418 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -164,7 +164,7 @@ class Network extends \Zotlabs\Web\Controller { )); } - nav_set_selected('Grid'); + nav_set_selected('Network'); $channel_acl = array( 'allow_cid' => $channel['channel_allow_cid'], diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index ebc444178..fc7c547ca 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -582,7 +582,7 @@ class Channel { '$lbl_vnot' => t('Show visual notifications including:'), - '$vnotify1' => array('vnotify1', t('Unseen grid activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no), + '$vnotify1' => array('vnotify1', t('Unseen stream activity'), ($vnotify & VNOTIFY_NETWORK), VNOTIFY_NETWORK, '', $yes_no), '$vnotify2' => array('vnotify2', t('Unseen channel activity'), ($vnotify & VNOTIFY_CHANNEL), VNOTIFY_CHANNEL, '', $yes_no), '$vnotify3' => array('vnotify3', t('Unseen private messages'), ($vnotify & VNOTIFY_MAIL), VNOTIFY_MAIL, t('Recommended'), $yes_no), '$vnotify4' => array('vnotify4', t('Upcoming events'), ($vnotify & VNOTIFY_EVENT), VNOTIFY_EVENT, '', $yes_no), diff --git a/Zotlabs/Module/Settings/Network.php b/Zotlabs/Module/Settings/Network.php index aaafe9255..ae02b06e9 100644 --- a/Zotlabs/Module/Settings/Network.php +++ b/Zotlabs/Module/Settings/Network.php @@ -55,7 +55,7 @@ class Network { '$rpath' => $rpath, '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), - '$title' => t('Activity Settings'), + '$title' => t('Stream Settings'), '$features' => process_module_features_get(local_channel(), $features), '$extra_settings_html' => $extra_settings_html, '$submit' => t('Submit') diff --git a/Zotlabs/Update/_1222.php b/Zotlabs/Update/_1222.php new file mode 100644 index 000000000..579025457 --- /dev/null +++ b/Zotlabs/Update/_1222.php @@ -0,0 +1,28 @@ + Date: Sat, 6 Oct 2018 16:52:42 +0200 Subject: rename widget titles --- Zotlabs/Widget/Activity_filter.php | 2 +- Zotlabs/Widget/Activity_order.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php index c27a5d48b..4ea0086dd 100644 --- a/Zotlabs/Widget/Activity_filter.php +++ b/Zotlabs/Widget/Activity_filter.php @@ -192,7 +192,7 @@ class Activity_filter { ]); $o .= replace_macros(get_markup_template('activity_filter_widget.tpl'), [ - '$title' => t('Activity Filters'), + '$title' => t('Stream Filters'), '$reset' => $reset, '$content' => $content, '$name' => $name diff --git a/Zotlabs/Widget/Activity_order.php b/Zotlabs/Widget/Activity_order.php index d9dbcc91f..1cba1ce8c 100644 --- a/Zotlabs/Widget/Activity_order.php +++ b/Zotlabs/Widget/Activity_order.php @@ -120,7 +120,7 @@ class Activity_order { ]); $o = replace_macros(get_markup_template('common_widget.tpl'), [ - '$title' => t('Activity Order'), + '$title' => t('Stream Order'), '$content' => $content, ]); } -- cgit v1.2.3 From d1745319318b47932cf5d4acf400bfbf62f94ddc Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 17:43:37 +0200 Subject: this did not actually make sense --- Zotlabs/Update/_1222.php | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1222.php b/Zotlabs/Update/_1222.php index 579025457..ad8d03197 100644 --- a/Zotlabs/Update/_1222.php +++ b/Zotlabs/Update/_1222.php @@ -2,8 +2,6 @@ namespace Zotlabs\Update; -use Zotlabs\Lib\Apps; - class _1222 { function run() { @@ -14,9 +12,6 @@ class _1222 { if($r1) { q("COMMIT"); - - Apps::import_system_apps(); - return UPDATE_SUCCESS; } -- cgit v1.2.3 From 66cf0852728d2f95ed3a5b7a304dbc7b79111831 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 20:29:32 +0200 Subject: move profile assign selector to profile settings and personal menu selector to channel_home settings and get rid of misc channel settings section. --- Zotlabs/Module/Settings/Channel.php | 27 +-------------------------- Zotlabs/Module/Settings/Channel_home.php | 30 +++++++++++++++++++++++++++++- Zotlabs/Module/Settings/Profiles.php | 13 +++++++++++-- 3 files changed, 41 insertions(+), 29 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index fc7c547ca..b0115d352 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -135,8 +135,6 @@ class Channel { $photo_path = ((x($_POST,'photo_path')) ? escape_tags(trim($_POST['photo_path'])) : ''); $attach_path = ((x($_POST,'attach_path')) ? escape_tags(trim($_POST['attach_path'])) : ''); - $channel_menu = ((x($_POST['channel_menu'])) ? htmlspecialchars_decode(trim($_POST['channel_menu']),ENT_QUOTES) : ''); - $expire_items = ((x($_POST,'expire_items')) ? intval($_POST['expire_items']) : 0); $expire_starred = ((x($_POST,'expire_starred')) ? intval($_POST['expire_starred']) : 0); $expire_photos = ((x($_POST,'expire_photos'))? intval($_POST['expire_photos']) : 0); @@ -157,8 +155,6 @@ class Channel { $defpermcat = ((x($_POST,'defpermcat')) ? notags(trim($_POST['defpermcat'])) : 'default'); $mailhost = ((array_key_exists('mailhost',$_POST)) ? notags(trim($_POST['mailhost'])) : ''); - $profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : ''); - $pageflags = $channel['channel_pageflags']; $existing_adult = (($pageflags & PAGE_ADULT) ? 1 : 0); @@ -246,7 +242,6 @@ class Channel { set_pconfig(local_channel(),'system','post_joingroup', $post_joingroup); set_pconfig(local_channel(),'system','post_profilechange', $post_profilechange); set_pconfig(local_channel(),'system','blocktags',$blocktags); - set_pconfig(local_channel(),'system','channel_menu',$channel_menu); set_pconfig(local_channel(),'system','vnotify',$vnotify); set_pconfig(local_channel(),'system','always_show_in_notices',$always_show_in_notices); set_pconfig(local_channel(),'system','evdays',$evdays); @@ -254,7 +249,6 @@ class Channel { set_pconfig(local_channel(),'system','attach_path',$attach_path); set_pconfig(local_channel(),'system','default_permcat',$defpermcat); set_pconfig(local_channel(),'system','email_notify_host',$mailhost); - set_pconfig(local_channel(),'system','profile_assign',$profile_assign); set_pconfig(local_channel(),'system','autoperms',$autoperms); $r = q("update channel set channel_name = '%s', channel_pageflags = %d, channel_timezone = '%s', channel_location = '%s', channel_notifyflags = %d, channel_max_anon_mail = %d, channel_max_friend_req = %d, channel_expire_days = %d $set_perms where channel_id = %d", @@ -460,18 +454,6 @@ class Channel { require_once('include/group.php'); $group_select = mini_group_select(local_channel(),$channel['channel_default_group']); - require_once('include/menu.php'); - $m1 = menu_list(local_channel()); - $menu = false; - if($m1) { - $menu = array(); - $current = get_pconfig(local_channel(),'system','channel_menu'); - $menu[] = array('name' => '', 'selected' => ((! $current) ? true : false)); - foreach($m1 as $m) { - $menu[] = array('name' => htmlspecialchars($m['menu_name'],ENT_COMPAT,'UTF-8'), 'selected' => (($m['menu_name'] === $current) ? ' selected="selected" ' : false)); - } - } - $evdays = get_pconfig(local_channel(),'system','evdays'); if(! $evdays) $evdays = 3; @@ -498,7 +480,7 @@ class Channel { if($vnotify === false) $vnotify = (-1); - $plugin = [ 'basic' => '', 'security' => '', 'notify' => '', 'misc' => '' ]; + $plugin = [ 'basic' => '', 'security' => '', 'notify' => '' ]; call_hooks('channel_settings',$plugin); $disable_discover_tab = intval(get_config('system','disable_discover_tab',1)) == 1; @@ -543,8 +525,6 @@ class Channel { '$permissions' => t('Default Privacy Group'), '$permdesc' => t("\x28click to open/close\x29"), '$aclselect' => populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromDescription(t('Use my default audience setting for the type of object published'))), - '$profseltxt' => t('Profile to assign new connections'), - '$profselect' => ((feature_enabled(local_channel(),'multi_profiles')) ? contact_profile_assign(get_pconfig(local_channel(),'system','profile_assign','')) : ''), '$allow_cid' => acl2json($perm_defaults['allow_cid']), '$allow_gid' => acl2json($perm_defaults['allow_gid']), @@ -604,7 +584,6 @@ class Channel { '$basic_addon' => $plugin['basic'], '$sec_addon' => $plugin['security'], '$notify_addon' => $plugin['notify'], - '$misc_addon' => $plugin['misc'], '$h_advn' => t('Advanced Account/Page Type Settings'), '$h_descadvn' => t('Change the behaviour of this account for special situations'), @@ -612,12 +591,8 @@ class Channel { '$lbl_misc' => t('Miscellaneous Settings'), '$photo_path' => array('photo_path', t('Default photo upload folder'), get_pconfig(local_channel(),'system','photo_path'), t('%Y - current year, %m - current month')), '$attach_path' => array('attach_path', t('Default file upload folder'), get_pconfig(local_channel(),'system','attach_path'), t('%Y - current year, %m - current month')), - '$menus' => $menu, - '$menu_desc' => t('Personal menu to display in your channel pages'), '$removeme' => t('Remove Channel'), '$removechannel' => t('Remove this channel.'), - '$firefoxshare' => t('Firefox Share $Projectname provider'), - )); call_hooks('settings_form',$o); diff --git a/Zotlabs/Module/Settings/Channel_home.php b/Zotlabs/Module/Settings/Channel_home.php index 0e916d530..b6ecf4ff1 100644 --- a/Zotlabs/Module/Settings/Channel_home.php +++ b/Zotlabs/Module/Settings/Channel_home.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +require_once('include/menu.php'); class Channel_home { @@ -18,8 +19,10 @@ class Channel_home { $channel_divmore_height = ((x($_POST,'channel_divmore_height')) ? intval($_POST['channel_divmore_height']) : 400); if($channel_divmore_height < 50) $channel_divmore_height = 50; - set_pconfig(local_channel(),'system','channel_divmore_height', $channel_divmore_height); + + $channel_menu = ((x($_POST['channel_menu'])) ? htmlspecialchars_decode(trim($_POST['channel_menu']),ENT_QUOTES) : ''); + set_pconfig(local_channel(),'system','channel_menu',$channel_menu); build_sync_packet(); @@ -43,12 +46,37 @@ class Channel_home { t('Click to expand content exceeding this height') ]; + $menus = menu_list(local_channel()); + if($menus) { + $current = get_pconfig(local_channel(),'system','channel_menu'); + $menu[] = ''; + foreach($menus as $m) { + $menu[$m['menu_name']] = htmlspecialchars($m['menu_name'],ENT_COMPAT,'UTF-8'); + } + + $menu_select = [ + 'channel_menu', + t('Personal menu to display in your channel pages'), + $current, + '', + $menu + ]; + } + $extra_settings_html = replace_macros(get_markup_template('field_input.tpl'), [ '$field' => $channel_divmore_height ] ); + if($menu) { + $extra_settings_html .= replace_macros(get_markup_template('field_select.tpl'), + [ + '$field' => $menu_select + ] + ); + } + $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( diff --git a/Zotlabs/Module/Settings/Profiles.php b/Zotlabs/Module/Settings/Profiles.php index 2dc037317..fb6abf664 100644 --- a/Zotlabs/Module/Settings/Profiles.php +++ b/Zotlabs/Module/Settings/Profiles.php @@ -2,6 +2,7 @@ namespace Zotlabs\Module\Settings; +require_once('include/selectors.php'); class Profiles { @@ -14,6 +15,9 @@ class Profiles { $features = get_module_features($module); process_module_features_post(local_channel(), $features, $_POST); + + $profile_assign = ((x($_POST,'profile_assign')) ? notags(trim($_POST['profile_assign'])) : ''); + set_pconfig(local_channel(),'system','profile_assign',$profile_assign); build_sync_packet(); @@ -30,6 +34,10 @@ class Profiles { $features = get_module_features($module); $rpath = (($_GET['rpath']) ? $_GET['rpath'] : ''); + $extra_settings_html = ''; + if(feature_enabled(local_channel(),'multi_profiles')) + $extra_settings_html = contact_profile_assign(get_pconfig(local_channel(),'system','profile_assign','')); + $tpl = get_markup_template("settings_module.tpl"); $o .= replace_macros($tpl, array( @@ -37,8 +45,9 @@ class Profiles { '$action_url' => 'settings/' . $module, '$form_security_token' => get_form_security_token('settings_' . $module), '$title' => t('Profiles Settings'), - '$features' => process_module_features_get(local_channel(), $features), - '$submit' => t('Submit') + '$features' => process_module_features_get(local_channel(), $features), + '$extra_settings_html' => $extra_settings_html, + '$submit' => t('Submit') )); return $o; -- cgit v1.2.3 From 6ffdf3880f89b83c701f866a6188ef6f079078c5 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 6 Oct 2018 20:48:29 +0200 Subject: another db update to get rid of the old view bookmarks entries --- Zotlabs/Update/_1223.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Zotlabs/Update/_1223.php (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1223.php b/Zotlabs/Update/_1223.php new file mode 100644 index 000000000..c6f05c806 --- /dev/null +++ b/Zotlabs/Update/_1223.php @@ -0,0 +1,23 @@ + Date: Sat, 6 Oct 2018 23:05:45 +0200 Subject: fix issue #1281 - hubloc default values --- Zotlabs/Update/_1224.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 Zotlabs/Update/_1224.php (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1224.php b/Zotlabs/Update/_1224.php new file mode 100644 index 000000000..d687afce7 --- /dev/null +++ b/Zotlabs/Update/_1224.php @@ -0,0 +1,25 @@ + Date: Sat, 6 Oct 2018 23:10:52 +0200 Subject: return success for postgres --- Zotlabs/Update/_1224.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Update/_1224.php b/Zotlabs/Update/_1224.php index d687afce7..d160cea5d 100644 --- a/Zotlabs/Update/_1224.php +++ b/Zotlabs/Update/_1224.php @@ -5,21 +5,24 @@ namespace Zotlabs\Update; class _1224 { function run() { - q("START TRANSACTION"); - if(ACTIVE_DBTYPE == DBTYPE_MYSQL) { + q("START TRANSACTION"); + $r1 = q("ALTER TABLE hubloc ALTER hubloc_id_url SET DEFAULT ''"); $r2 = q("ALTER TABLE hubloc ALTER hubloc_site_id SET DEFAULT ''"); - } - if($r1 && $r2) { - q("COMMIT"); + if($r1 && $r2) { + q("COMMIT"); + return UPDATE_SUCCESS; + } + + q("ROLLBACK"); + return UPDATE_FAILED; + } + if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { return UPDATE_SUCCESS; } - q("ROLLBACK"); - return UPDATE_FAILED; - } } -- cgit v1.2.3 From 108855aca212a858bf60d85d6418bae5450111d0 Mon Sep 17 00:00:00 2001 From: "M. Dent" Date: Sun, 7 Oct 2018 19:43:03 +0200 Subject: Fix (potential) runaway cron --- Zotlabs/Daemon/Master.php | 122 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Daemon/Master.php b/Zotlabs/Daemon/Master.php index 580df97db..6fb674d60 100644 --- a/Zotlabs/Daemon/Master.php +++ b/Zotlabs/Daemon/Master.php @@ -3,7 +3,6 @@ namespace Zotlabs\Daemon; if(array_search( __file__ , get_included_files()) === 0) { - require_once('include/cli_startup.php'); array_shift($argv); $argc = count($argv); @@ -17,14 +16,129 @@ if(array_search( __file__ , get_included_files()) === 0) { class Master { + static public $queueworker = null; + static public function Summon($arr) { proc_run('php','Zotlabs/Daemon/Master.php',$arr); } static public function Release($argc,$argv) { cli_startup(); - logger('Master: release: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); - $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; - $cls::run($argc,$argv); + + $maxworkers = get_config('system','max_queue_workers'); + + if (!$maxworkers || $maxworkers == 0) { + logger('Master: release: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); + $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; + $cls::run($argc,$argv); + self::ClearQueue(); + } else { + logger('Master: enqueue: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); + $workinfo = ['argc'=>$argc,'argv'=>$argv]; + q("insert into config (cat,k,v) values ('queuework','%s','%s')", + dbesc(uniqid('workitem:',true)), + dbesc(serialize($workinfo))); + self::Process(); + } + } + + static public function GetWorkerID() { + $maxworkers = get_config('system','max_queue_workers'); + $maxworkers = ($maxworkers) ? $maxworkers : 3; + + $workermaxage = get_config('system','max_queue_worker_age'); + $workermaxage = ($workermaxage) ? $workermaxage : 300; + + $workers = q("select * from config where cat='queueworkers' and k like '%s'", 'workerstarted_%'); + + if (count($workers) > $maxworkers) { + foreach ($workers as $idx => $worker) { + $curtime = time(); + if (($time - $worker['v']) > $workermaxage) { + $k = explode('_',$worker['k']); + q("delete from config where cat='queueworkers' and k='%s'", + 'workerstarted_'.$k[1]); + q("update config set k='workitem' where cat='queuework' and k='%s'", + 'workitem_'.$k[1]); + unset($workers[$idx]); + } + } + if (count($workers) > $maxworkers) { + return false; + } + } + return uniqid(); + + } + + static public function Process() { + + self::$queueworker = self::GetWorkerID(); + + if (!self::$queueworker) { + logger('Master: unable to obtain worker ID.'); + killme(); + } + + set_config('queueworkers','workerstarted_'.self::$queueworker,time()); + + $workersleep = get_config('system','queue_worker_sleep'); + $workersleep = ($workersleep) ? $workersleep : 5; + cli_startup(); + + $work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1", + 'workitem_'.self::$queueworker, + dbesc('workitem:%')); + $jobs = 0; + while ($work) { + $workitem = q("select * from config where cat='queuework' and k='%s'", + 'workitem_'.self::$queueworker); + + if (isset($workitem[0])) { + $jobs++; + $workinfo = unserialize($workitem[0]['v']); + $argc = $workinfo['argc']; + $argv = $workinfo['argv']; + logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); + $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; + $cls::run($argc,$argv); + + //Right now we assume that if we get a return, everything is OK. + //At some point we may want to test whether the run returns true/false + // and requeue the work to be tried again. But we probably want + // to implement some sort of "retry interval" first. + + q("delete from config where cat='queuework' and k='%s'", + 'workitem_'.self::$queueworker); + } else { + break; + } + sleep ($workersleep); + $work = q("update config set k='%s' where cat='queuework' and k like '%s' limit 1", + 'workitem_'.self::$queueworker, + dbesc('workitem:%')); + + } + logger('Master: Worker Thread: queue items processed:' . $jobs); + q("delete from config where cat='queueworkers' and k='%s'", + 'workerstarted_'.self::$queueworker); } + + static public function ClearQueue() { + $work = q("select * from config where cat='queuework' and k like '%s'", + 'workitem_%', + dbesc('workitem%')); + foreach ($work as $workitem) { + $workinfo = unserialize($workitem['v']); + $argc = $workinfo['argc']; + $argv = $workinfo['argv']; + logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); + $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; + $cls::run($argc,$argv); + } + $work = q("delete from config where cat='queuework' and k like '%s'", + 'workitem_%', + dbesc('workitem%')); + } + } -- cgit v1.2.3 From 60d5443f000dd77c64b425c33ed341ef822734e8 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Sun, 7 Oct 2018 19:18:35 -0400 Subject: Fix too many arguments --- Zotlabs/Daemon/Master.php | 2 -- 1 file changed, 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Daemon/Master.php b/Zotlabs/Daemon/Master.php index 6fb674d60..ed1adf8fb 100644 --- a/Zotlabs/Daemon/Master.php +++ b/Zotlabs/Daemon/Master.php @@ -126,7 +126,6 @@ class Master { static public function ClearQueue() { $work = q("select * from config where cat='queuework' and k like '%s'", - 'workitem_%', dbesc('workitem%')); foreach ($work as $workitem) { $workinfo = unserialize($workitem['v']); @@ -137,7 +136,6 @@ class Master { $cls::run($argc,$argv); } $work = q("delete from config where cat='queuework' and k like '%s'", - 'workitem_%', dbesc('workitem%')); } -- cgit v1.2.3 From 69584f541d052e6da410d9cd782656eb31fae22d Mon Sep 17 00:00:00 2001 From: zotlabs Date: Sun, 7 Oct 2018 22:12:49 -0700 Subject: hubzilla core issue #1278 - page update always reloads if noscript content is enabled --- 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 8b46ebb79..d1755c183 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -12,7 +12,7 @@ class Display extends \Zotlabs\Web\Controller { function get($update = 0, $load = false) { - $noscript_content = get_config('system', 'noscript_content', '1'); + $noscript_content = (get_config('system', 'noscript_content', '1') && (! $update)); $module_format = 'html'; @@ -299,7 +299,6 @@ class Display extends \Zotlabs\Web\Controller { require_once('include/channel.php'); $sys = get_sys_channel(); $sysid = $sys['channel_id']; - if(local_channel()) { $r = q("SELECT item.parent AS item_id from item WHERE uid = %d @@ -340,7 +339,7 @@ class Display extends \Zotlabs\Web\Controller { else { $r = array(); } - + if($r) { $parents_str = ids_to_querystr($r,'item_id'); if($parents_str) { -- cgit v1.2.3 From e0568f33e82de15e5d5a38ec7697d6afd67352f3 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 8 Oct 2018 11:25:49 +0200 Subject: the root cause for doubled entries is fixed now --- Zotlabs/Module/Siteinfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Siteinfo.php b/Zotlabs/Module/Siteinfo.php index 79b94662d..a8c5bda91 100644 --- a/Zotlabs/Module/Siteinfo.php +++ b/Zotlabs/Module/Siteinfo.php @@ -32,7 +32,7 @@ class Siteinfo extends \Zotlabs\Web\Controller { '$transport_link' => 'https://zotlabs.com', '$additional_text' => t('Additional federated transport protocols:'), - '$additional_fed' => implode(', ',array_unique($federated)), + '$additional_fed' => implode(', ', $federated), '$prj_version' => ((get_config('system','hidden_version_siteinfo')) ? '' : sprintf( t('Version %s'), \Zotlabs\Lib\System::get_project_version())), '$prj_linktxt' => t('Project homepage'), '$prj_srctxt' => t('Developer homepage'), -- cgit v1.2.3 From f0b7a7e5d38a92268a67d8dedf69f97d88b4c542 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 8 Oct 2018 11:38:45 +0200 Subject: typo --- Zotlabs/Module/Admin/Site.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index e67f9f165..09b038729 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -311,7 +311,7 @@ class Site { '$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), t("This is displayed on the public server site list."), $access_choices), '$register_text' => array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")), '$role' => $role, - '$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")), + '$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'pubstream' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")), '$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')), '$abandon_days' => array('abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')), '$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")), -- cgit v1.2.3 From 93a310582f044d35f0a3583671053595fefdbedb Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Sun, 7 Oct 2018 19:08:47 -0400 Subject: Implement custom escaping --- Zotlabs/Lib/NativeWiki.php | 36 +++++++++++++++++++++++++++++++++--- Zotlabs/Lib/NativeWikiPage.php | 12 ++++++++---- Zotlabs/Module/Wiki.php | 34 +++++++++++++++++++++------------- Zotlabs/Widget/Wiki_pages.php | 3 ++- 4 files changed, 64 insertions(+), 21 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/NativeWiki.php b/Zotlabs/Lib/NativeWiki.php index 6f916216e..4309d3f6e 100644 --- a/Zotlabs/Lib/NativeWiki.php +++ b/Zotlabs/Lib/NativeWiki.php @@ -26,7 +26,8 @@ class NativeWiki { $w['rawName'] = get_iconfig($w, 'wiki', 'rawName'); $w['htmlName'] = escape_tags($w['rawName']); - $w['urlName'] = urlencode(urlencode($w['rawName'])); + //$w['urlName'] = urlencode(urlencode($w['rawName'])); + $w['urlName'] = self::name_encode($w['rawName']); $w['mimeType'] = get_iconfig($w, 'wiki', 'mimeType'); $w['typelock'] = get_iconfig($w, 'wiki', 'typelock'); $w['lockstate'] = (($w['allow_cid'] || $w['allow_gid'] || $w['deny_cid'] || $w['deny_gid']) ? 'lock' : 'unlock'); @@ -233,7 +234,8 @@ class NativeWiki { 'wiki' => $w, 'rawName' => $rawName, 'htmlName' => escape_tags($rawName), - 'urlName' => urlencode(urlencode($rawName)), + //'urlName' => urlencode(urlencode($rawName)), + 'urlName' => self::name_encode($rawName), 'mimeType' => $mimeType, 'typelock' => $typelock ); @@ -249,7 +251,8 @@ class NativeWiki { WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d AND item_deleted = 0 $sql_extra limit 1", dbesc(NWIKI_ITEM_RESOURCE_TYPE), - dbesc(urldecode($urlName)), + //dbesc(urldecode($urlName)), + dbesc($urlName), intval($uid) ); @@ -286,4 +289,31 @@ class NativeWiki { return array('read' => true, 'write' => $write, 'success' => true); } } + + public static function name_encode ($string) { + + $encoding = mb_internal_encoding(); + mb_internal_encoding("UTF-8"); + $ret = mb_ereg_replace_callback ('[^A-Za-z0-9\-\_\.\~]',function ($char) { + $charhex = unpack('H*',$char[0]); + $ret = '('.$charhex[1].')'; + return $ret; + } + ,$string); + mb_internal_encoding($encoding); + return $ret; + } + + public static function name_decode ($string) { + + $encoding = mb_internal_encoding(); + mb_internal_encoding("UTF-8"); + $ret = mb_ereg_replace_callback ('(\(([0-9a-f]+)\))',function ($chars) { + return pack('H*',$chars[2]); + } + ,$string); + mb_internal_encoding($encoding); + return $ret; + } + } diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php index d4875bbaf..d0f522ec1 100644 --- a/Zotlabs/Lib/NativeWikiPage.php +++ b/Zotlabs/Lib/NativeWikiPage.php @@ -44,7 +44,8 @@ class NativeWikiPage { $pages[] = [ 'resource_id' => $resource_id, 'title' => escape_tags($title), - 'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))), + //'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))), + 'url' => Zlib\NativeWiki::name_encode($title), 'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id'] ]; } @@ -98,7 +99,8 @@ class NativeWikiPage { $page = [ 'rawName' => $name, 'htmlName' => escape_tags($name), - 'urlName' => urlencode($name), + //'urlName' => urlencode($name), + Zlib\NativeWiki::name_encode($name) ]; @@ -154,7 +156,8 @@ class NativeWikiPage { $page = [ 'rawName' => $pageNewName, 'htmlName' => escape_tags($pageNewName), - 'urlName' => urlencode(escape_tags($pageNewName)) + //'urlName' => urlencode(escape_tags($pageNewName)) + Zlib\NativeWiki::name_encode($pageNewName) ]; return [ 'success' => true, 'page' => $page ]; @@ -527,7 +530,8 @@ class NativeWikiPage { $pages = $pageURLs = array(); foreach ($match[1] as $m) { // TODO: Why do we need to double urlencode for this to work? - $pageURLs[] = urlencode(urlencode(escape_tags($m))); + //$pageURLs[] = urlencode(urlencode(escape_tags($m))); + $pageURLs[] = Zlib\NativeWiki::name_encode(escape_tags($m)); $pages[] = $m; } $idx = 0; diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 6be39214e..3b8f44124 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -237,7 +237,8 @@ class Wiki extends Controller { // /wiki/channel/wiki -> No page was specified, so redirect to Home.md - $wikiUrlName = urlencode(argv(2)); + //$wikiUrlName = urlencode(argv(2)); + $wikiUrlName = NativeWiki::name_encode(argv(2)); goaway(z_root() . '/' . argv(0) . '/' . argv(1) . '/' . $wikiUrlName . '/Home'); case 4: @@ -246,7 +247,8 @@ class Wiki extends Controller { // GET /wiki/channel/wiki/page // Fetch the wiki info and determine observer permissions - $wikiUrlName = urldecode(argv(2)); + //$wikiUrlName = urldecode(argv(2)); + $wikiUrlName = NativeWiki::name_decode(argv(2)); $page_name = ''; $ignore_language = false; @@ -262,7 +264,8 @@ class Wiki extends Controller { $page_name .= argv($x); } - $pageUrlName = urldecode($page_name); + //$pageUrlName = urldecode($page_name); + $pageUrlName = NativeWiki::name_decode($page_name); $langPageUrlName = urldecode(\App::$language . '/' . $page_name); $w = NativeWiki::exists_by_name($owner['channel_id'], $wikiUrlName); @@ -289,8 +292,10 @@ class Wiki extends Controller { $wiki_editor = true; } - $wikiheaderName = urldecode($wikiUrlName); - $wikiheaderPage = urldecode($pageUrlName); + //$wikiheaderName = urldecode($wikiUrlName); + $wikiheaderName = NativeWiki::name_decode($wikiUrlName); + //$wikiheaderPage = urldecode($pageUrlName); + $wikiheaderPage = NativeWiki::name_decode($pageUrlName); $renamePage = (($wikiheaderPage === 'Home') ? '' : t('Rename page')); $sharePage = t('Share'); @@ -360,13 +365,14 @@ class Wiki extends Controller { $currenttype = $types[$mimeType]; $placeholder = t('Short description of your changes (optional)'); - + + $zrl = urlencode( z_root() . '/wiki/' . argv(1) . '/' . $wikiUrlName . '/' . $pageUrlName ); $o .= replace_macros(get_markup_template('wiki.tpl'),array( '$wikiheaderName' => $wikiheaderName, '$wikiheaderPage' => $wikiheaderPage, '$renamePage' => $renamePage, '$sharePage' => $sharePage, - '$shareLink' => urlencode('#^[zrl=' . z_root() . '/wiki/' . argv(1) . '/' . $wikiUrlName . '/' . $pageUrlName . ']' . '[ ' . $owner['channel_name'] . ' ] ' . $wikiheaderName . ' - ' . $wikiheaderPage . '[/zrl]'), + '$shareLink' => '#^[zrl=' . $zrl . ']' . '[ ' . $owner['channel_name'] . ' ] ' . $wikiheaderName . ' - ' . $wikiheaderPage . '[/zrl]', '$showPageControls' => $showPageControls, '$editOrSourceLabel' => (($showPageControls) ? t('Edit') : t('Source')), '$tools_label' => 'Page Tools', @@ -465,7 +471,8 @@ class Wiki extends Controller { $wiki['postVisible'] = ((intval($_POST['postVisible'])) ? 1 : 0); $wiki['rawName'] = $name; $wiki['htmlName'] = escape_tags($name); - $wiki['urlName'] = urlencode(urlencode($name)); + //$wiki['urlName'] = urlencode(urlencode($name)); + $wiki['urlName'] = NativeWiki::name_encode($name); $wiki['mimeType'] = $_POST['mimeType']; $wiki['typelock'] = $_POST['typelock']; @@ -514,7 +521,8 @@ class Wiki extends Controller { $arr = []; - $arr['urlName'] = urlencode(urlencode($_POST['origRawName'])); + //$arr['urlName'] = urlencode(urlencode($_POST['origRawName'])); + $arr['urlName'] = NativeWiki::name_encode($_POST['origRawName']); if($_POST['updateRawName']) $arr['updateRawName'] = $_POST['updateRawName']; @@ -525,7 +533,7 @@ class Wiki extends Controller { return; //not reached } - $wiki = NativeWiki::exists_by_name($owner['channel_id'], urldecode($arr['urlName'])); + $wiki = NativeWiki::exists_by_name($owner['channel_id'], $arr['urlName']); if($wiki['resource_id']) { @@ -590,7 +598,7 @@ class Wiki extends Controller { // backslashes won't work well in the javascript functions $name = str_replace('\\','',$name); - if(urlencode(escape_tags($name)) === '') { + if(NativeWiki::name_encode(escape_tags($name)) === '') { json_return_and_die(array('message' => 'Error creating page. Invalid name (' . print_r($_POST,true) . ').', 'success' => false)); } @@ -798,7 +806,7 @@ class Wiki extends Controller { if ($pageUrlName === 'Home') { json_return_and_die(array('message' => 'Cannot rename Home','success' => false)); } - if(urlencode(escape_tags($pageNewName)) === '') { + if(NativeWiki::encode_name(escape_tags($pageNewName)) === '') { json_return_and_die(array('message' => 'Error renaming page. Invalid name.', 'success' => false)); } // Determine if observer has permission to rename pages @@ -814,7 +822,7 @@ class Wiki extends Controller { if($renamed['success']) { $commit = NativeWikiPage::commit(array( 'channel_id' => $owner['channel_id'], - 'commit_msg' => 'Renamed ' . urldecode($pageUrlName) . ' to ' . $renamed['page']['htmlName'], + 'commit_msg' => 'Renamed ' . NativeWiki::name_decode($pageUrlName) . ' to ' . $renamed['page']['htmlName'], 'resource_id' => $resource_id, 'observer_hash' => $observer_hash, 'pageUrlName' => $pageNewName diff --git a/Zotlabs/Widget/Wiki_pages.php b/Zotlabs/Widget/Wiki_pages.php index ecd2c9100..831662ca9 100644 --- a/Zotlabs/Widget/Wiki_pages.php +++ b/Zotlabs/Widget/Wiki_pages.php @@ -2,6 +2,7 @@ namespace Zotlabs\Widget; +use Zotlabs\Lib\NativeWiki; class Wiki_pages { @@ -21,7 +22,7 @@ class Wiki_pages { $can_create = perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'write_wiki'); $can_delete = ((local_channel() && (local_channel() == \App::$profile['uid'])) ? true : false); - $pageName = addslashes(escape_tags(urldecode(argv(3)))); + $pageName = NativeWiki::name_decode(escape_tags(argv(3))); return replace_macros(get_markup_template('wiki_page_not_found.tpl'), array( '$resource_id' => $arr['resource_id'], -- cgit v1.2.3 From 709665846e66f093109730691b31d9e094d02088 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Mon, 8 Oct 2018 13:22:39 -0400 Subject: Rework Wiki encoding scheme. --- Zotlabs/Lib/NativeWiki.php | 1 + Zotlabs/Lib/NativeWikiPage.php | 3 +-- Zotlabs/Module/Wiki.php | 42 ++++++++++++++++++++++++------------------ Zotlabs/Widget/Wiki_pages.php | 5 +++-- 4 files changed, 29 insertions(+), 22 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/NativeWiki.php b/Zotlabs/Lib/NativeWiki.php index 4309d3f6e..65f40748c 100644 --- a/Zotlabs/Lib/NativeWiki.php +++ b/Zotlabs/Lib/NativeWiki.php @@ -292,6 +292,7 @@ class NativeWiki { public static function name_encode ($string) { + $string = html_entity_decode($string); $encoding = mb_internal_encoding(); mb_internal_encoding("UTF-8"); $ret = mb_ereg_replace_callback ('[^A-Za-z0-9\-\_\.\~]',function ($char) { diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php index d0f522ec1..ebdcb4740 100644 --- a/Zotlabs/Lib/NativeWikiPage.php +++ b/Zotlabs/Lib/NativeWikiPage.php @@ -100,7 +100,7 @@ class NativeWikiPage { 'rawName' => $name, 'htmlName' => escape_tags($name), //'urlName' => urlencode($name), - Zlib\NativeWiki::name_encode($name) + 'urlName' => Zlib\NativeWiki::name_encode($name) ]; @@ -368,7 +368,6 @@ class NativeWikiPage { unset($item['id']); unset($item['author']); - $item['parent'] = 0; $item['body'] = $content; $item['author_xchan'] = $observer_hash; diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 3b8f44124..ead7eea6a 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -266,7 +266,7 @@ class Wiki extends Controller { //$pageUrlName = urldecode($page_name); $pageUrlName = NativeWiki::name_decode($page_name); - $langPageUrlName = urldecode(\App::$language . '/' . $page_name); + $langPageUrlName = \App::$language . '/' . $pageUrlName; $w = NativeWiki::exists_by_name($owner['channel_id'], $wikiUrlName); @@ -293,9 +293,9 @@ class Wiki extends Controller { } //$wikiheaderName = urldecode($wikiUrlName); - $wikiheaderName = NativeWiki::name_decode($wikiUrlName); + $wikiheaderName = $wikiUrlName; //$wikiheaderPage = urldecode($pageUrlName); - $wikiheaderPage = NativeWiki::name_decode($pageUrlName); + $wikiheaderPage = $pageUrlName; $renamePage = (($wikiheaderPage === 'Home') ? '' : t('Rename page')); $sharePage = t('Share'); @@ -320,7 +320,7 @@ class Wiki extends Controller { //json_return_and_die(array('pages' => $page_list_html, 'message' => '', 'success' => true)); notice( t('Error retrieving page content') . EOL); //goaway(z_root() . '/' . argv(0) . '/' . argv(1) ); - $renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName); + $renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName)); $showPageControls = $wiki_editor; } else { @@ -334,21 +334,25 @@ class Wiki extends Controller { // Render the Markdown-formatted page content in HTML if($mimeType == 'text/bbcode') { - $renderedContent = NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))), argv(0) . '/' . argv(1) . '/' . $wikiUrlName); + $renderedContent = NativeWikiPage::convert_links($content,argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName)); + $renderedContent = zidify_links(smilies(bbcode($renderedContent))); + //$renderedContent = NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))), argv(0) . '/' . argv(1) . '/' . $wikiUrlName); } elseif($mimeType === 'text/plain') { $renderedContent = str_replace(["\n",' ',"\t"],[EOL,' ','    '],htmlentities($content,ENT_COMPAT,'UTF-8',false)); } elseif($mimeType === 'text/markdown') { $content = MarkdownSoap::unescape($content); - $html = NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(NativeWikiPage::bbcode($content)))); - $renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName); + //$html = NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(NativeWikiPage::bbcode($content)))); + //$renderedContent = NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName); + $html = NativeWikiPage::convert_links($content, argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName)); + $renderedContent = NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(NativeWikiPage::bbcode($html)))); } $showPageControls = $wiki_editor; } break; // default: // Strip the extraneous URL components -// goaway('/' . argv(0) . '/' . argv(1) . '/' . $wikiUrlName . '/' . $pageUrlName); +// goaway('/' . argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName) . '/' . $pageUrlName); } @@ -366,7 +370,7 @@ class Wiki extends Controller { $placeholder = t('Short description of your changes (optional)'); - $zrl = urlencode( z_root() . '/wiki/' . argv(1) . '/' . $wikiUrlName . '/' . $pageUrlName ); + $zrl = urlencode( z_root() . '/wiki/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName) . '/' . NativeWiki::name_encode($pageUrlName) ); $o .= replace_macros(get_markup_template('wiki.tpl'),array( '$wikiheaderName' => $wikiheaderName, '$wikiheaderPage' => $wikiheaderPage, @@ -435,16 +439,17 @@ class Wiki extends Controller { $mimeType = $_POST['mimetype']; if($mimeType === 'text/bbcode') { - $html = NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))),$wikiURL); + $linkconverted = NativeWikiPage::convert_links($content,$wikiURL); + $html = zidify_links(smilies(bbcode($linkconverted))); } elseif($mimeType === 'text/markdown') { - $bb = NativeWikiPage::bbcode($content); + $linkconverted = NativeWikiPage::convert_links($content,$wikiURL); + $bb = NativeWikiPage::bbcode($linkconverted); $x = new MarkdownSoap($bb); $md = $x->clean(); $md = MarkdownSoap::unescape($md); $html = MarkdownExtra::defaultTransform($md); $html = NativeWikiPage::generate_toc(zidify_text($html)); - $html = NativeWikiPage::convert_links($html,$wikiURL); } elseif($mimeType === 'text/plain') { $html = str_replace(["\n",' ',"\t"],[EOL,' ','    '],htmlentities($content,ENT_COMPAT,'UTF-8',false)); @@ -498,10 +503,10 @@ class Wiki extends Controller { $homePage = NativeWikiPage::create_page($owner['channel_id'],$observer_hash,'Home', $r['item']['resource_id'], $wiki['mimeType']); if(! $homePage['success']) { notice( t('Wiki created, but error creating Home page.')); - goaway(z_root() . '/wiki/' . $nick . '/' . $wiki['urlName']); + goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName'])); } NativeWiki::sync_a_wiki_item($owner['channel_id'],$homePage['item_id'],$r['item']['resource_id']); - goaway(z_root() . '/wiki/' . $nick . '/' . $wiki['urlName'] . '/' . $homePage['page']['urlName']); + goaway(z_root() . '/wiki/' . $nick . '/' . NativeWiki::name_encode($wiki['urlName']) . '/' . NativeWiki::name_encode($homePage['page']['urlName'])); } else { notice( t('Error creating wiki')); @@ -593,7 +598,7 @@ class Wiki extends Controller { json_return_and_die(array('success' => false)); } - $name = $_POST['pageName']; //Get new page name + $name = isset($_POST['pageName']) ? $_POST['pageName'] : $_POST['missingPageName']; //Get new page name // backslashes won't work well in the javascript functions $name = str_replace('\\','',$name); @@ -615,10 +620,11 @@ class Wiki extends Controller { if($commit['success']) { NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); - json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']), 'success' => true)); + //json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']), 'success' => true)); + json_return_and_die(array('url' => '/' . argv(0) . '/' . argv(1) . '/' . $page['wiki']['urlName'] . '/' . $page['page']['urlName'], 'success' => true)); } else { - json_return_and_die(array('message' => 'Error making git commit','url' => '/' . argv(0) . '/' . argv(1) . '/' . urlencode($page['wiki']['urlName']) . '/' . urlencode($page['page']['urlName']),'success' => false)); + json_return_and_die(array('message' => 'Error making git commit','url' => '/' . argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($page['wiki']['urlName']) . '/' . NativeWiki::name_encode($page['page']['urlName']),'success' => false)); } @@ -685,7 +691,7 @@ class Wiki extends Controller { if($commit['success']) { NativeWiki::sync_a_wiki_item($owner['channel_id'],$commit['item_id'],$resource_id); - json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true)); + json_return_and_die(array('message' => 'Wiki git repo commit made', 'success' => true , 'content' => $content)); } else { json_return_and_die(array('message' => 'Error making git commit','success' => false)); diff --git a/Zotlabs/Widget/Wiki_pages.php b/Zotlabs/Widget/Wiki_pages.php index 831662ca9..dee0a2229 100644 --- a/Zotlabs/Widget/Wiki_pages.php +++ b/Zotlabs/Widget/Wiki_pages.php @@ -11,7 +11,7 @@ class Wiki_pages { return; $c = channelx_by_nick(argv(1)); - $w = \Zotlabs\Lib\NativeWiki::exists_by_name($c['channel_id'],urldecode(argv(2))); + $w = \Zotlabs\Lib\NativeWiki::exists_by_name($c['channel_id'],NativeWiki::name_decode(argv(2))); $arr = array( 'resource_id' => $w['resource_id'], 'channel_id' => $c['channel_id'], @@ -24,6 +24,7 @@ class Wiki_pages { $can_delete = ((local_channel() && (local_channel() == \App::$profile['uid'])) ? true : false); $pageName = NativeWiki::name_decode(escape_tags(argv(3))); + $wikiname = $w['urlName']; return replace_macros(get_markup_template('wiki_page_not_found.tpl'), array( '$resource_id' => $arr['resource_id'], '$channel_address' => $arr['channel_address'], @@ -49,7 +50,7 @@ class Wiki_pages { if(! $arr['resource_id']) { $c = channelx_by_nick(argv(1)); - $w = \Zotlabs\Lib\NativeWiki::exists_by_name($c['channel_id'],urldecode(argv(2))); + $w = \Zotlabs\Lib\NativeWiki::exists_by_name($c['channel_id'],NativeWiki::name_decode(argv(2))); $arr = array( 'resource_id' => $w['resource_id'], 'channel_id' => $c['channel_id'], -- cgit v1.2.3 From c6f3298f7864756f4a9b7827e8490a3ee859f82f Mon Sep 17 00:00:00 2001 From: zotlabs Date: Tue, 9 Oct 2018 22:37:53 -0700 Subject: SECURITY: signature issue --- Zotlabs/Module/Magic.php | 7 ++++++- Zotlabs/Module/Owa.php | 2 +- Zotlabs/Web/HTTPSig.php | 15 +++++++++++++++ Zotlabs/Zot/Finger.php | 7 +++++++ 4 files changed, 29 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php index be6866592..71737eef8 100644 --- a/Zotlabs/Module/Magic.php +++ b/Zotlabs/Module/Magic.php @@ -146,12 +146,17 @@ class Magic extends \Zotlabs\Web\Controller { $dest = strip_zids($dest); $dest = strip_query_param($dest,'f'); + $data = json_encode([ 'OpenWebAuth' => random_string() ]); + $headers = []; $headers['Accept'] = 'application/x-zot+json' ; $headers['X-Open-Web-Auth'] = random_string(); + $headers['Host'] = $parsed['host']; + $headers['Digest'] = 'SHA-256=' . \Zotlabs\Web\HTTPSig::generate_digest($data,false); + $headers = \Zotlabs\Web\HTTPSig::create_sig('',$headers,$channel['channel_prvkey'], 'acct:' . $channel['channel_address'] . '@' . \App::get_hostname(),false,true,'sha512'); - $x = z_fetch_url($basepath . '/owa',false,$redirects,[ 'headers' => $headers ]); + $x = z_post_url($basepath . '/owa',$data,$redirects,[ 'headers' => $headers ]); if($x['success']) { $j = json_decode($x['body'],true); diff --git a/Zotlabs/Module/Owa.php b/Zotlabs/Module/Owa.php index da26748b3..4a488086f 100644 --- a/Zotlabs/Module/Owa.php +++ b/Zotlabs/Module/Owa.php @@ -45,7 +45,7 @@ class Owa extends \Zotlabs\Web\Controller { } if($r) { foreach($r as $hubloc) { - $verified = \Zotlabs\Web\HTTPSig::verify('',$hubloc['xchan_pubkey']); + $verified = \Zotlabs\Web\HTTPSig::verify(file_get_contents('php://input'),$hubloc['xchan_pubkey']); if($verified && $verified['header_signed'] && $verified['header_valid']) { logger('OWA header: ' . print_r($verified,true),LOGGER_DATA); logger('OWA success: ' . $hubloc['hubloc_addr'],LOGGER_DATA); diff --git a/Zotlabs/Web/HTTPSig.php b/Zotlabs/Web/HTTPSig.php index df66ecf5c..ec7bb0d67 100644 --- a/Zotlabs/Web/HTTPSig.php +++ b/Zotlabs/Web/HTTPSig.php @@ -104,6 +104,21 @@ class HTTPSig { if(strpos($h,'.')) { $spoofable = true; } + if($h === 'host' && (strpos(strtolower(\App::get_hostname()),strtolower($headers[$h])) === false)) { + logger('bad host: ' . $sig_block['keyId'] . ' != ' . $headers[$h]); + return $result; + } + if($h === 'date') { + $d = new \DateTime($headers[$h]); + $d->setTimeZone(new \DateTimeZone('UTC')); + $dplus = datetime_convert('UTC','UTC','now + 1 day'); + $dminus = datetime_convert('UTC','UTC','now - 1 day'); + $c = $d->format('Y-m-d H:i:s'); + if($c > $dplus || $c < $dminus) { + logger('bad time: ' . $c); + return $result; + } + } } $signed_data = rtrim($signed_data,"\n"); diff --git a/Zotlabs/Zot/Finger.php b/Zotlabs/Zot/Finger.php index 559f9657a..1d20f5822 100644 --- a/Zotlabs/Zot/Finger.php +++ b/Zotlabs/Zot/Finger.php @@ -71,6 +71,11 @@ class Finger { $url = 'https://' . $host; } + $m = parse_url($url); + if($m) { + $parsed_host = strtolower($m['host']); + } + $rhs = '/.well-known/zot-info'; $https = ((strpos($url,'https://') === 0) ? true : false); @@ -88,6 +93,8 @@ class Finger { $headers = []; $headers['X-Zot-Channel'] = $channel['channel_address'] . '@' . \App::get_hostname(); $headers['X-Zot-Nonce'] = random_string(); + $headers['Host'] = $parsed['host']; + $xhead = \Zotlabs\Web\HTTPSig::create_sig('',$headers,$channel['channel_prvkey'], 'acct:' . $channel['channel_address'] . '@' . \App::get_hostname(),false); -- cgit v1.2.3 From d29caa099af2d132978e634a454a29d5c85c23fe Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 10 Oct 2018 10:39:28 +0200 Subject: fix some more wiki issues --- Zotlabs/Lib/NativeWiki.php | 2 +- Zotlabs/Lib/NativeWikiPage.php | 2 +- Zotlabs/Module/Wiki.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/NativeWiki.php b/Zotlabs/Lib/NativeWiki.php index 65f40748c..cdabbc3e9 100644 --- a/Zotlabs/Lib/NativeWiki.php +++ b/Zotlabs/Lib/NativeWiki.php @@ -252,7 +252,7 @@ class NativeWiki { AND item_deleted = 0 $sql_extra limit 1", dbesc(NWIKI_ITEM_RESOURCE_TYPE), //dbesc(urldecode($urlName)), - dbesc($urlName), + dbesc(self::name_decode($urlName)), intval($uid) ); diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php index ebdcb4740..8d21fac5e 100644 --- a/Zotlabs/Lib/NativeWikiPage.php +++ b/Zotlabs/Lib/NativeWikiPage.php @@ -157,7 +157,7 @@ class NativeWikiPage { 'rawName' => $pageNewName, 'htmlName' => escape_tags($pageNewName), //'urlName' => urlencode(escape_tags($pageNewName)) - Zlib\NativeWiki::name_encode($pageNewName) + 'urlName' => Zlib\NativeWiki::name_encode($pageNewName) ]; return [ 'success' => true, 'page' => $page ]; diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index ead7eea6a..25823da62 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -293,9 +293,9 @@ class Wiki extends Controller { } //$wikiheaderName = urldecode($wikiUrlName); - $wikiheaderName = $wikiUrlName; + $wikiheaderName = NativeWiki::name_decode($wikiUrlName); //$wikiheaderPage = urldecode($pageUrlName); - $wikiheaderPage = $pageUrlName; + $wikiheaderPage = NativeWiki::name_decode($pageUrlName); $renamePage = (($wikiheaderPage === 'Home') ? '' : t('Rename page')); $sharePage = t('Share'); @@ -812,7 +812,7 @@ class Wiki extends Controller { if ($pageUrlName === 'Home') { json_return_and_die(array('message' => 'Cannot rename Home','success' => false)); } - if(NativeWiki::encode_name(escape_tags($pageNewName)) === '') { + if(NativeWiki::name_encode(escape_tags($pageNewName)) === '') { json_return_and_die(array('message' => 'Error renaming page. Invalid name.', 'success' => false)); } // Determine if observer has permission to rename pages -- cgit v1.2.3 From 802ccdff4ade258f09fd3dca4ff4aa63cf5f9ac6 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Wed, 10 Oct 2018 23:00:59 +0200 Subject: fix issue in zot finger --- Zotlabs/Zot/Finger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Zot/Finger.php b/Zotlabs/Zot/Finger.php index 1d20f5822..77634777a 100644 --- a/Zotlabs/Zot/Finger.php +++ b/Zotlabs/Zot/Finger.php @@ -93,7 +93,7 @@ class Finger { $headers = []; $headers['X-Zot-Channel'] = $channel['channel_address'] . '@' . \App::get_hostname(); $headers['X-Zot-Nonce'] = random_string(); - $headers['Host'] = $parsed['host']; + $headers['Host'] = $parsed_host; $xhead = \Zotlabs\Web\HTTPSig::create_sig('',$headers,$channel['channel_prvkey'], 'acct:' . $channel['channel_address'] . '@' . \App::get_hostname(),false); -- cgit v1.2.3 From bad4ea6e65a45ac2523a9a7c2ec624ad2535b652 Mon Sep 17 00:00:00 2001 From: "M.Dent" Date: Wed, 10 Oct 2018 22:46:00 -0400 Subject: Add wiki_preprocess hook and documentation --- Zotlabs/Lib/NativeWikiPage.php | 2 +- Zotlabs/Module/Wiki.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php index 8d21fac5e..dddd26af3 100644 --- a/Zotlabs/Lib/NativeWikiPage.php +++ b/Zotlabs/Lib/NativeWikiPage.php @@ -619,7 +619,7 @@ class NativeWikiPage { $s = str_replace('[observer.webname]', '', $s); $s = str_replace('[observer.photo]', '', $s); } - + return $s; } diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 25823da62..05d6e85cd 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -331,6 +331,10 @@ class Wiki extends Controller { $sampleContent = t('New page'); $content = (($p['content'] == '') ? $sampleContent : $p['content']); + + $hookinfo = ['content' => $content, 'mimetype' => $mimeType]; + call_hooks('wiki_preprocess',$hookinfo); + $content = $hookinfo['content']; // Render the Markdown-formatted page content in HTML if($mimeType == 'text/bbcode') { -- cgit v1.2.3 From c6bfd5e7befedf79ab6f7e70902e5fb2aa69fa6f Mon Sep 17 00:00:00 2001 From: zotlabs Date: Thu, 11 Oct 2018 21:28:47 -0700 Subject: verify some edge case http signatures --- Zotlabs/Web/HTTPSig.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Web/HTTPSig.php b/Zotlabs/Web/HTTPSig.php index ec7bb0d67..f27aa0556 100644 --- a/Zotlabs/Web/HTTPSig.php +++ b/Zotlabs/Web/HTTPSig.php @@ -52,6 +52,7 @@ class HTTPSig { $h = new \Zotlabs\Web\HTTPHeaders($data['header']); $headers = $h->fetcharr(); $body = $data['body']; + $headers['(request-target)'] = $data['request_target']; } else { @@ -60,6 +61,7 @@ class HTTPSig { strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']; $headers['content-type'] = $_SERVER['CONTENT_TYPE']; + $headers['content-length'] = $_SERVER['CONTENT_LENGTH']; foreach($_SERVER as $k => $v) { if(strpos($k,'HTTP_') === 0) { @@ -104,10 +106,6 @@ class HTTPSig { if(strpos($h,'.')) { $spoofable = true; } - if($h === 'host' && (strpos(strtolower(\App::get_hostname()),strtolower($headers[$h])) === false)) { - logger('bad host: ' . $sig_block['keyId'] . ' != ' . $headers[$h]); - return $result; - } if($h === 'date') { $d = new \DateTime($headers[$h]); $d->setTimeZone(new \DateTimeZone('UTC')); -- cgit v1.2.3 From 5b43db7171d8b42a99be23c8c4958a800d2fb7c5 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 15 Oct 2018 11:13:04 +0000 Subject: fix wiki issue with wiki page links when using bbcode (cherry picked from commit df62037c4a722606e84e28dd4d62e89dcc999980) --- Zotlabs/Module/Wiki.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 05d6e85cd..892810241 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -338,9 +338,8 @@ class Wiki extends Controller { // Render the Markdown-formatted page content in HTML if($mimeType == 'text/bbcode') { - $renderedContent = NativeWikiPage::convert_links($content,argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName)); - $renderedContent = zidify_links(smilies(bbcode($renderedContent))); - //$renderedContent = NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))), argv(0) . '/' . argv(1) . '/' . $wikiUrlName); + $renderedContent = zidify_links(smilies(bbcode($content))); + $renderedContent = NativeWikiPage::convert_links($renderedContent,argv(0) . '/' . argv(1) . '/' . NativeWiki::name_encode($wikiUrlName)); } elseif($mimeType === 'text/plain') { $renderedContent = str_replace(["\n",' ',"\t"],[EOL,' ','    '],htmlentities($content,ENT_COMPAT,'UTF-8',false)); -- cgit v1.2.3 From fa5537bfc0fe0919da118888208140a10d54c5b6 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 15 Oct 2018 13:43:55 +0000 Subject: allow to undelete deleted base apps (cherry picked from commit 3588c4ab996f462f11cd89255e6d511441ed0315) --- Zotlabs/Lib/Apps.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index e6757497a..b13658be2 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -532,8 +532,8 @@ class Apps { '$installed' => $installed, '$action_label' => (($hosturl && in_array($mode, ['view','install'])) ? $install_action : ''), '$edit' => ((local_channel() && $installed && $mode == 'edit') ? t('Edit') : ''), - '$delete' => ((local_channel() && $installed && $mode == 'edit') ? t('Delete') : ''), - '$undelete' => ((local_channel() && $installed && $mode == 'edit') ? t('Undelete') : ''), + '$delete' => ((local_channel() && $mode == 'edit') ? t('Delete') : ''), + '$undelete' => ((local_channel() && $mode == 'edit') ? t('Undelete') : ''), '$settings_url' => ((local_channel() && $installed && $mode == 'list') ? $papp['settings_url'] : ''), '$deleted' => $papp['deleted'], '$feature' => (($papp['embed'] || $mode == 'edit') ? false : true), -- cgit v1.2.3 From 34b4b658658fe6aefbc13da5d03262eb16b2443f Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Mon, 15 Oct 2018 18:18:25 +0000 Subject: add missing features section to newmember widget (cherry picked from commit 25a74f366460144d12287b51bdbdb48ebcadfb98) --- Zotlabs/Widget/Newmember.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Widget/Newmember.php b/Zotlabs/Widget/Newmember.php index e57cf5171..224f7a8a2 100644 --- a/Zotlabs/Widget/Newmember.php +++ b/Zotlabs/Widget/Newmember.php @@ -51,7 +51,13 @@ class Newmember { t('Miscellaneous'), [ 'settings' => t('Settings'), - 'help' => t('Documentation'), + 'help' => t('Documentation'), + ], + + t('Missing Features?'), + [ + 'apps' => t('Pin apps to navigation bar'), + 'apps/available' => t('Install more apps') ] ]; -- cgit v1.2.3 From 84d40361178af961dc93aa0c53bb49cbfe31da3f Mon Sep 17 00:00:00 2001 From: Mario Date: Tue, 16 Oct 2018 19:19:16 +0000 Subject: Merge branch 'fix-master-rate-limiter' into 'dev' Fix master rate limiter See merge request hubzilla/core!1341 (cherry picked from commit e38e85572e148e1cf684810f6435001b32d8c7fc) 49eff772 Fix worker age calculation be30dc9e Move logger to debug/all b6a9be88 Delete duplicate queue items --- Zotlabs/Daemon/Master.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Daemon/Master.php b/Zotlabs/Daemon/Master.php index ed1adf8fb..3a71ee578 100644 --- a/Zotlabs/Daemon/Master.php +++ b/Zotlabs/Daemon/Master.php @@ -53,8 +53,10 @@ class Master { if (count($workers) > $maxworkers) { foreach ($workers as $idx => $worker) { - $curtime = time(); - if (($time - $worker['v']) > $workermaxage) { + $curtime = time(); + $age = (intval($curtime) - intval($worker['v'])); + if ( $age > $workermaxage) { + logger("Prune worker: ".$worker['k'], LOGGER_ALL, LOGGER_DEBUG); $k = explode('_',$worker['k']); q("delete from config where cat='queueworkers' and k='%s'", 'workerstarted_'.$k[1]); @@ -100,6 +102,11 @@ class Master { $argc = $workinfo['argc']; $argv = $workinfo['argv']; logger('Master: process: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG); + + //Delete unclaimed duplicate workitems. + q("delete from config where cat='queuework' and k='workitem' and v='%s'", + serialize($argv)); + $cls = '\\Zotlabs\\Daemon\\' . $argv[0]; $cls::run($argc,$argv); -- cgit v1.2.3 From 90e9c37d35bcc96e39efacf69881d6e5f685fd1f Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Tue, 16 Oct 2018 11:46:03 +0000 Subject: improve posting to mod pconfig via ajax (cherry picked from commit ae875734e270dbe9840e87f07aa10f11a1af1d89) --- Zotlabs/Module/Pconfig.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'Zotlabs') diff --git a/Zotlabs/Module/Pconfig.php b/Zotlabs/Module/Pconfig.php index b6264bddc..7c82bac7d 100644 --- a/Zotlabs/Module/Pconfig.php +++ b/Zotlabs/Module/Pconfig.php @@ -13,14 +13,15 @@ class Pconfig extends \Zotlabs\Web\Controller { return; - if($_SESSION['delegate']) - return; + if($_SESSION['delegate']) + return; check_form_security_token_redirectOnErr('/pconfig', 'pconfig'); $cat = trim(escape_tags($_POST['cat'])); $k = trim(escape_tags($_POST['k'])); $v = trim($_POST['v']); + $aj = intval($_POST['aj']); if(in_array(argv(2),$this->disallowed_pconfig())) { notice( t('This setting requires special processing and editing has been blocked.') . EOL); @@ -33,9 +34,12 @@ class Pconfig extends \Zotlabs\Web\Controller { set_pconfig(local_channel(),$cat,$k,$v); build_sync_packet(); - - goaway(z_root() . '/pconfig/' . $cat . '/' . $k); - + + if($aj) + killme(); + else + goaway(z_root() . '/pconfig/' . $cat . '/' . $k); + } -- cgit v1.2.3