diff options
Diffstat (limited to 'Zotlabs')
75 files changed, 1486 insertions, 464 deletions
diff --git a/Zotlabs/Access/PermissionRoles.php b/Zotlabs/Access/PermissionRoles.php index 9855a05c4..c8b4953a5 100644 --- a/Zotlabs/Access/PermissionRoles.php +++ b/Zotlabs/Access/PermissionRoles.php @@ -308,6 +308,8 @@ class PermissionRoles { ] ]; + call_hooks('list_permission_roles',$roles); + return $roles; } diff --git a/Zotlabs/Access/Permissions.php b/Zotlabs/Access/Permissions.php index bca40a9c1..20dc22a72 100644 --- a/Zotlabs/Access/Permissions.php +++ b/Zotlabs/Access/Permissions.php @@ -67,7 +67,7 @@ class Permissions { 'post_comments' => t('Can comment on or like my posts'), 'post_mail' => t('Can send me private mail messages'), 'post_like' => t('Can like/dislike profiles and profile things'), - 'tag_deliver' => t('Can forward to all my channel connections via @+ mentions in posts'), + 'tag_deliver' => t('Can forward to all my channel connections via ! mentions in posts'), 'chat' => t('Can chat with me'), 'republish' => t('Can source my public posts in derived channels'), 'delegate' => t('Can administer my channel') diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php index 01c43262a..d1c516f96 100644 --- a/Zotlabs/Daemon/Cron.php +++ b/Zotlabs/Daemon/Cron.php @@ -50,14 +50,19 @@ class Cron { // expire any expired items - $r = q("select id from item where expires > '2001-01-01 00:00:00' and expires < %s + $r = q("select id,item_wall from item where expires > '2001-01-01 00:00:00' and expires < %s and item_deleted = 0 ", db_utcnow() ); if($r) { require_once('include/items.php'); - foreach($r as $rr) - drop_item($rr['id'],false); + foreach($r as $rr) { + 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'] ] ); + } + } } diff --git a/Zotlabs/Daemon/Poller.php b/Zotlabs/Daemon/Poller.php index e4bc9c143..49151437c 100644 --- a/Zotlabs/Daemon/Poller.php +++ b/Zotlabs/Daemon/Poller.php @@ -71,14 +71,18 @@ class Poller { $randfunc = db_getfunc('RAND'); - $contacts = q("SELECT * FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash + $contacts = q("SELECT abook.abook_updated, abook.abook_connected, abook.abook_feed, + abook.abook_channel, abook.abook_id, abook.abook_archived, abook.abook_pending, + abook.abook_ignored, abook.abook_blocked, + xchan.xchan_network, + account.account_lastlog, account.account_flags + FROM abook LEFT JOIN xchan on abook_xchan = xchan_hash LEFT JOIN account on abook_account = account_id where abook_self = 0 $sql_extra AND (( account_flags = %d ) OR ( account_flags = %d )) $abandon_sql ORDER BY $randfunc", intval(ACCOUNT_OK), intval(ACCOUNT_UNVERIFIED) // FIXME - ); if($contacts) { diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php index 2e9bb0703..37e717f58 100644 --- a/Zotlabs/Lib/ActivityStreams.php +++ b/Zotlabs/Lib/ActivityStreams.php @@ -9,6 +9,7 @@ namespace Zotlabs\Lib; */ class ActivityStreams { + public $raw = null; public $data; public $valid = false; public $id = ''; @@ -33,7 +34,9 @@ class ActivityStreams { */ function __construct($string) { + $this->raw = $string; $this->data = json_decode($string, true); + if($this->data) { $this->valid = true; } @@ -204,7 +207,7 @@ class ActivityStreams { } $x = z_fetch_url($url, true, $redirects, - ['headers' => [ 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/activity+json' ]]); + ['headers' => [ 'Accept: application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ]]); if($x['success']) return json_decode($x['body'], true); diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 24cb4a626..c2ec5c967 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -13,7 +13,12 @@ require_once('include/channel.php'); class Apps { - static public $installed_system_apps = null; + static public $available_apps = null; + static public $installed_apps = null; + + static public $base_apps = null; + + static public function get_system_apps($translate = true) { @@ -45,6 +50,8 @@ class Apps { } } + call_hooks('get_system_apps',$ret); + return $ret; } @@ -53,22 +60,52 @@ class Apps { static public function import_system_apps() { if(! local_channel()) return; + + self::$base_apps = get_config('system','base_apps',[ + 'Connections', + 'Suggest Channels', + 'Grid', + 'Settings', + 'Files', + 'Channel Home', + 'View Profile', + 'Photos', + 'Events', + 'Directory', + 'Search', + 'Help', + 'Mail', + 'Profile Photo' + ]); + $apps = self::get_system_apps(false); - self::$installed_system_apps = q("select * from app where app_system = 1 and app_channel = %d", + self::$available_apps = q("select * from app where app_channel = 0"); + + self::$installed_apps = q("select * from app where app_channel = %d", intval(local_channel()) ); if($apps) { foreach($apps as $app) { $id = self::check_install_system_app($app); + + // $id will be boolean true or false to install an app, or an integer id to update an existing app + if($id !== false) { + $app['uid'] = 0; + $app['guid'] = hash('whirlpool',$app['name']); + $app['system'] = 1; + self::app_install(0,$app); + } + + $id = self::check_install_personal_app($app); // $id will be boolean true or false to install an app, or an integer id to update an existing app if($id === false) continue; if($id !== true) { // if we already installed this app, but it changed, preserve any categories we created - $s = ''; - $r = q("select * from term where otype = %d and oid = %d", + $s = EMPTY_STR; + $r = q("select term from term where otype = %d and oid = %d", intval(TERM_OBJ_APP), intval($id) ); @@ -85,6 +122,7 @@ class Apps { $app['guid'] = hash('whirlpool',$app['name']); $app['system'] = 1; self::app_install(local_channel(),$app); + } } } @@ -95,11 +133,11 @@ class Apps { */ static public function check_install_system_app($app) { - if((! is_array(self::$installed_system_apps)) || (! count(self::$installed_system_apps))) { + if((! is_array(self::$available_apps)) || (! count(self::$available_apps))) { return true; } $notfound = true; - foreach(self::$installed_system_apps as $iapp) { + foreach(self::$available_apps as $iapp) { if($iapp['app_id'] == hash('whirlpool',$app['name'])) { $notfound = false; if(($iapp['app_version'] != $app['version']) @@ -113,6 +151,31 @@ class Apps { } + /** + * Install the system app if no system apps have been installed, or if a new system app + * is discovered, or if the version of a system app changes. + */ + + + + static public function check_install_personal_app($app) { + $installed = false; + foreach(self::$installed_apps as $iapp) { + if($iapp['app_id'] == hash('whirlpool',$app['name'])) { + $installed = true; + if(($iapp['app_version'] != $app['version']) + || ($app['plugin'] && (! $iapp['app_plugin']))) { + return intval($iapp['app_id']); + } + } + } + if(! $installed && in_array($app['name'],self::$base_apps)) { + return true; + } + return false; + } + + static public function app_name_compare($a,$b) { return strcasecmp($a['name'],$b['name']); } @@ -233,7 +296,6 @@ class Apps { 'View Bookmarks' => t('View Bookmarks'), 'My Chatrooms' => t('My Chatrooms'), 'Connections' => t('Connections'), - 'Firefox Share' => t('Firefox Share'), 'Remote Diagnostics' => t('Remote Diagnostics'), 'Suggest Channels' => t('Suggest Channels'), 'Login' => t('Login'), @@ -288,6 +350,7 @@ class Apps { * modes: * view: normal mode for viewing an app via bbcode from a conversation or page * provides install/update button if you're logged in locally + * install: like view but does not display app-bin options if they are present * list: normal mode for viewing an app on the app page * no buttons are shown * edit: viewing the app page in editing mode provides a delete button @@ -300,7 +363,7 @@ class Apps { return; if(! $papp['photo']) - $papp['photo'] = z_root() . '/' . get_default_profile_photo(80); + $papp['photo'] = 'icon:gear'; self::translate_system_apps($papp); @@ -400,12 +463,15 @@ class Apps { )); } + if($mode === 'install') { + $papp['embed'] = true; + } return replace_macros(get_markup_template('app.tpl'),array( '$app' => $papp, '$icon' => $icon, '$hosturl' => $hosturl, '$purchase' => (($papp['page'] && (! $installed)) ? t('Purchase') : ''), - '$install' => (($hosturl && $mode == 'view') ? $install_action : ''), + '$install' => (($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') : ''), @@ -468,21 +534,13 @@ class Apps { intval(TERM_OBJ_APP), intval($x[0]['id']) ); - if($x[0]['app_system']) { - $r = q("update app set app_deleted = 1 where app_id = '%s' and app_channel = %d", - dbesc($app['guid']), - intval($uid) - ); - } - else { - $r = q("delete from app where app_id = '%s' and app_channel = %d", - dbesc($app['guid']), - intval($uid) - ); + $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)); - } + // 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); @@ -736,12 +794,19 @@ class Apps { $darray = array(); $ret = array('success' => false); + $sys = get_sys_channel(); + + $darray['app_url'] = ((x($arr,'url')) ? $arr['url'] : ''); $darray['app_channel'] = ((x($arr,'uid')) ? $arr['uid'] : 0); - if((! $darray['app_url']) || (! $darray['app_channel'])) + if(! $darray['app_url']) return $ret; + if((! $arr['uid']) && (! $arr['author'])) { + $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); $arr['photo'] = $x[1]; @@ -875,7 +940,7 @@ class Apps { // if updating an embed app, don't mess with any existing categories. - if(array_key_exists('embed',$arr) && intval($arr['embed'])) + if(array_key_exists('embed',$arr) && intval($arr['embed']) && (intval($darray['app_channel']))) return $ret; if($x) { diff --git a/Zotlabs/Lib/MessageFilter.php b/Zotlabs/Lib/MessageFilter.php new file mode 100644 index 000000000..eb0fc3d2c --- /dev/null +++ b/Zotlabs/Lib/MessageFilter.php @@ -0,0 +1,79 @@ +<?php + +namespace Zotlabs\Lib; + + + +class MessageFilter { + + + static public function evaluate($item,$incl,$excl) { + + require_once('include/html2plain.php'); + + unobscure($item); + + $text = prepare_text($item['body'],$item['mimetype']); + $text = html2plain(($item['title']) ? $item['title'] . ' ' . $text : $text); + + + $lang = null; + + if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false)) { + $lang = detect_language($text); + } + + $tags = ((is_array($item['term']) && count($item['term'])) ? $item['term'] : false); + + // exclude always has priority + + $exclude = (($excl) ? explode("\n",$excl) : null); + + if($exclude) { + foreach($exclude as $word) { + $word = trim($word); + if(! $word) + continue; + if(substr($word,0,1) === '#' && $tags) { + foreach($tags as $t) + if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*'))) + return false; + } + elseif((strpos($word,'/') === 0) && preg_match($word,$text)) + return false; + elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0)) + return false; + elseif(stristr($text,$word) !== false) + return false; + } + } + + $include = (($incl) ? explode("\n",$incl) : null); + + if($include) { + foreach($include as $word) { + $word = trim($word); + if(! $word) + continue; + if(substr($word,0,1) === '#' && $tags) { + foreach($tags as $t) + if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*'))) + return true; + } + elseif((strpos($word,'/') === 0) && preg_match($word,$text)) + return true; + elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0)) + return true; + elseif(stristr($text,$word) !== false) + return true; + } + } + else { + return true; + } + + return false; + } + + +} diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 61a012f9d..ed78ae00b 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -102,6 +102,13 @@ class ThreadItem { if($item['author']['xchan_network'] === 'rss') $shareable = true; + $privacy_warning = false; + if(($item['item_private'] == 1) && ($item['owner']['xchan_network'] === 'activitypub')) { + $recips = get_iconfig($item['parent'], 'activitypub', 'recips'); + + if(! in_array($observer['xchan_url'], $recips['to'])) + $privacy_warning = true; + } $mode = $conv->get_mode(); @@ -141,6 +148,10 @@ class ThreadItem { 'delete' => t('Delete'), ); } + elseif(is_site_admin()) { + $drop = [ 'dropping' => true, 'delete' => t('Admin Delete') ]; + } + // FIXME if($observer_is_pageowner) { $multidrop = array( @@ -232,16 +243,9 @@ class ThreadItem { // FIXME check this permission if(($conv->get_profile_owner() == local_channel()) && (! array_key_exists('real_uid',$item))) { -// FIXME we don't need all this stuff, some can be done in the template - $star = array( - 'do' => t("Add Star"), - 'undo' => t("Remove Star"), 'toggle' => t("Toggle Star Status"), - 'classdo' => ((intval($item['item_starred'])) ? "hidden" : ""), - 'classundo' => ((intval($item['item_starred'])) ? "" : "hidden"), 'isstarred' => ((intval($item['item_starred'])) ? true : false), - 'starred' => t('starred'), ); } @@ -366,6 +370,7 @@ class ThreadItem { 'editedtime' => (($item['edited'] != $item['created']) ? sprintf( t('last edited: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['edited'], 'r')) : ''), 'expiretime' => (($item['expires'] > NULL_DATE) ? sprintf( t('Expires: %s'), datetime_convert('UTC', date_default_timezone_get(), $item['expires'], 'r')):''), 'lock' => $lock, + 'privacy_warning' => $privacy_warning, 'verified' => $verified, 'unverified' => $unverified, 'forged' => $forged, @@ -756,7 +761,7 @@ class ThreadItem { '$edquote' => t('Quote'), '$edcode' => t('Code'), '$edimg' => t('Image'), - '$edatt' => t('Attach File'), + '$edatt' => t('Attach/Upload file'), '$edurl' => t('Insert Link'), '$edvideo' => t('Video'), '$preview' => t('Preview'), // ((feature_enabled($conv->get_profile_owner(),'preview')) ? t('Preview') : ''), diff --git a/Zotlabs/Module/Acl.php b/Zotlabs/Module/Acl.php index 4c5883e88..0c2ad7522 100644 --- a/Zotlabs/Module/Acl.php +++ b/Zotlabs/Module/Acl.php @@ -24,7 +24,7 @@ class Acl extends \Zotlabs\Web\Controller { function init() { - logger('mod_acl: ' . print_r($_REQUEST,true),LOGGER_DATA); + // logger('mod_acl: ' . print_r($_GET,true),LOGGER_DATA); $start = (x($_REQUEST,'start') ? $_REQUEST['start'] : 0); $count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 500); @@ -94,8 +94,7 @@ class Acl extends \Zotlabs\Web\Controller { . " then POSITION('" . protect_sprintf(dbesc($search)) . "' IN xchan_name) else position('" . protect_sprintf(dbesc(punify($search))) . "' IN xchan_addr) end, "; - $col = ((strpos($search,'@') !== false) ? 'xchan_addr' : 'xchan_name' ); - $sql_extra3 = "AND $col like " . protect_sprintf( "'%" . dbesc(($col === 'xchan_addr') ? punify($search) : $search) . "%'" ) . " "; + $sql_extra3 = "AND ( xchan_addr like " . protect_sprintf( "'%" . dbesc(punify($search)) . "%'" ) . " OR xchan_name like " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ) "; } else { @@ -268,15 +267,15 @@ class Acl extends \Zotlabs\Web\Controller { }); } } - if(intval(get_config('system','taganyone')) || intval(get_pconfig(local_channel(),'system','taganyone'))) { - if((count($r) < 100) && $type == 'c') { - $r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self - FROM xchan - WHERE xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" - ); - if($r2) - $r = array_merge($r,$r2); - } + if((count($r) < 100) && $type == 'c') { + $r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self + FROM xchan + WHERE xchan_deleted = 0 and not xchan_network in ('rss','anon','unknown') $sql_extra2 order by $order_extra2 xchan_name asc" + ); + if($r2) { + $r = array_merge($r,$r2); + $r = unique_multidim_array($r,'hash'); + } } } elseif($type == 'm') { @@ -337,24 +336,23 @@ class Acl extends \Zotlabs\Web\Controller { if($r) { foreach($r as $g) { - if(($g['network'] === 'rss') && ($type != 'a')) + if(in_array($g['network'],['rss','anon','unknown']) && ($type != 'a')) continue; $g['hash'] = urlencode($g['hash']); if(! $g['nick']) { - $t = explode(' ',strtolower($g['name'])); - $g['nick'] = $t[0] . '@'; + $g['nick'] = $g['url']; } - if(in_array($g['hash'],$permitted) && in_array($type, [ 'c', 'f' ]) && (! $noforums)) { + if(in_array($g['hash'],$permitted) && $type === 'f' && (! $noforums)) { $contacts[] = array( "type" => "c", "photo" => "images/twopeople.png", - "name" => $g['name'] . (($type === 'f') ? '' : '+'), - "id" => urlencode($g['id']) . (($type === 'f') ? '' : '+'), + "name" => $g['name'], + "id" => urlencode($g['id']), "xid" => $g['hash'], - "link" => $g['nick'], + "link" => (($g['nick']) ? $g['nick'] : $g['url']), "nick" => substr($g['nick'],0,strpos($g['nick'],'@')), "self" => (intval($g['abook_self']) ? 'abook-self' : ''), "taggable" => 'taggable', @@ -368,8 +366,8 @@ class Acl extends \Zotlabs\Web\Controller { "name" => $g['name'], "id" => urlencode($g['id']), "xid" => $g['hash'], - "link" => $g['nick'], - "nick" => (($g['nick']) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']), + "link" => (($g['nick']) ? $g['nick'] : $g['url']), + "nick" => ((strpos($g['nick'],'@')) ? substr($g['nick'],0,strpos($g['nick'],'@')) : $g['nick']), "self" => (intval($g['abook_self']) ? 'abook-self' : ''), "taggable" => '', "label" => '', diff --git a/Zotlabs/Module/Admin.php b/Zotlabs/Module/Admin.php index 30f3dfa48..2df8dc25d 100644 --- a/Zotlabs/Module/Admin.php +++ b/Zotlabs/Module/Admin.php @@ -100,8 +100,12 @@ class Admin extends \Zotlabs\Web\Controller { } // pending registrations - $r = q("SELECT COUNT(id) AS rtotal FROM register WHERE uid != '0'"); - $pending = $r[0]['rtotal']; + + $pdg = q("SELECT account.*, register.hash from account left join register on account_id = register.uid where (account_flags & %d ) > 0 ", + intval(ACCOUNT_PENDING) + ); + + $pending = (($pdg) ? count($pdg) : 0); // available channels, primary and clones $channels = array(); @@ -140,7 +144,7 @@ class Admin extends \Zotlabs\Web\Controller { '$accounts' => array( t('Registered accounts'), $accounts), '$pending' => array( t('Pending registrations'), $pending), '$channels' => array( t('Registered channels'), $channels), - '$plugins' => array( t('Active plugins'), $plugins ), + '$plugins' => array( t('Active addons'), $plugins ), '$version' => array( t('Version'), STD_VERSION), '$vmaster' => array( t('Repository version (master)'), $vmaster), '$vdev' => array( t('Repository version (dev)'), $vdev), diff --git a/Zotlabs/Module/Admin/Plugins.php b/Zotlabs/Module/Admin/Addons.php index feb29e9d6..b35922aef 100644 --- a/Zotlabs/Module/Admin/Plugins.php +++ b/Zotlabs/Module/Admin/Addons.php @@ -2,10 +2,10 @@ namespace Zotlabs\Module\Admin; -use \Zotlabs\Storage\GitRepo as GitRepo; +use \Zotlabs\Storage\GitRepo; use \Michelf\MarkdownExtra; -class Plugins { +class Addons { /** * @brief @@ -20,7 +20,7 @@ class Plugins { $func($a); } - goaway(z_root() . '/admin/plugins/' . argv(2) ); + goaway(z_root() . '/admin/addons/' . argv(2) ); } elseif(argc() > 2) { switch(argv(2)) { @@ -243,7 +243,7 @@ class Plugins { } /** - * @brief Plugins admin page. + * @brief Addons admin page. * * @return string with parsed HTML */ @@ -278,7 +278,7 @@ class Plugins { $info['disabled'] = 1-intval($x); if (x($_GET,"a") && $_GET['a']=="t"){ - check_form_security_token_redirectOnErr('/admin/plugins', 'admin_plugins', 't'); + check_form_security_token_redirectOnErr('/admin/addons', 'admin_addons', 't'); $pinstalled = false; // Toggle plugin status $idx = array_search($plugin, \App::$plugins); @@ -298,9 +298,9 @@ class Plugins { if($pinstalled) { @require_once("addon/$plugin/$plugin.php"); if(function_exists($plugin.'_plugin_admin')) - goaway(z_root() . '/admin/plugins/' . $plugin); + goaway(z_root() . '/admin/addons/' . $plugin); } - goaway(z_root() . '/admin/plugins' ); + goaway(z_root() . '/admin/addons' ); } // display plugin details @@ -339,7 +339,7 @@ class Plugins { $t = get_markup_template('admin_plugins_details.tpl'); return replace_macros($t, array( '$title' => t('Administration'), - '$page' => t('Plugins'), + '$page' => t('Addons'), '$toggle' => t('Toggle'), '$settings' => t('Settings'), '$baseurl' => z_root(), @@ -358,11 +358,11 @@ class Plugins { '$disabled' => t('Disabled - version incompatibility'), '$admin_form' => $admin_form, - '$function' => 'plugins', + '$function' => 'addons', '$screenshot' => '', '$readme' => $readme, - '$form_security_token' => get_form_security_token('admin_plugins'), + '$form_security_token' => get_form_security_token('admin_addons'), )); } @@ -407,11 +407,11 @@ class Plugins { $admin_plugins_add_repo_form= replace_macros( get_markup_template('admin_plugins_addrepo.tpl'), array( - '$post' => 'admin/plugins/addrepo', - '$desc' => t('Enter the public git repository URL of the plugin repo.'), - '$repoURL' => array('repoURL', t('Plugin repo git URL'), '', ''), + '$post' => 'admin/addons/addrepo', + '$desc' => t('Enter the public git repository URL of the addon repo.'), + '$repoURL' => array('repoURL', t('Addon repo git URL'), '', ''), '$repoName' => array('repoName', t('Custom repo name'), '', '', t('(optional)')), - '$submit' => t('Download Plugin Repo') + '$submit' => t('Download Addon Repo') ) ); $newRepoModalID = random_string(3); @@ -434,17 +434,17 @@ class Plugins { $t = get_markup_template('admin_plugins.tpl'); return replace_macros($t, array( '$title' => t('Administration'), - '$page' => t('Plugins'), + '$page' => t('Addons'), '$submit' => t('Submit'), '$baseurl' => z_root(), - '$function' => 'plugins', + '$function' => 'addons', '$plugins' => $plugins, '$disabled' => t('Disabled - version incompatibility'), - '$form_security_token' => get_form_security_token('admin_plugins'), + '$form_security_token' => get_form_security_token('admin_addons'), '$allowManageRepos' => $allowManageRepos, '$managerepos' => t('Manage Repos'), - '$installedtitle' => t('Installed Plugin Repositories'), - '$addnewrepotitle' => t('Install a New Plugin Repository'), + '$installedtitle' => t('Installed Addon Repositories'), + '$addnewrepotitle' => t('Install a New Addon Repository'), '$expandform' => false, '$form' => $admin_plugins_add_repo_form, '$newRepoModal' => $newRepoModal, diff --git a/Zotlabs/Module/Admin/Security.php b/Zotlabs/Module/Admin/Security.php index 49e1ccf42..80c1d85b7 100644 --- a/Zotlabs/Module/Admin/Security.php +++ b/Zotlabs/Module/Admin/Security.php @@ -16,7 +16,13 @@ class Security { $block_public = ((x($_POST,'block_public')) ? True : False); set_config('system','block_public',$block_public); - + + $cloud_noroot = ((x($_POST,'cloud_noroot')) ? 1 : 0); + set_config('system','cloud_disable_siteroot',1 - $cloud_noroot); + + $cloud_disksize = ((x($_POST,'cloud_disksize')) ? 1 : 0); + set_config('system','cloud_report_disksize',$cloud_disksize); + $ws = $this->trim_array_elems(explode("\n",$_POST['whitelisted_sites'])); set_config('system','whitelisted_sites',$ws); @@ -87,6 +93,8 @@ class Security { '$page' => t('Security'), '$form_security_token' => get_form_security_token('admin_security'), '$block_public' => array('block_public', t("Block public"), get_config('system','block_public'), t("Check to block public access to all otherwise public personal pages on this site unless you are currently authenticated.")), + '$cloud_noroot' => [ 'cloud_noroot', t('Provide a cloud root directory'), 1 - intval(get_config('system','cloud_disable_siteroot')), t('The cloud root directory lists all channel names which provide public files') ], + '$cloud_disksize' => [ 'cloud_disksize', t('Show total disk space available to cloud uploads'), intval(get_config('system','cloud_report_disksize')), '' ], '$transport_security' => array('transport_security', t('Set "Transport Security" HTTP header'),intval(get_config('system','transport_security_header')),''), '$content_security' => array('content_security', t('Set "Content Security Policy" HTTP header'),intval(get_config('system','content_security_policy')),''), '$allowed_email' => array('allowed_email', t("Allowed email domains"), get_config('system','allowed_email'), t("Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains")), diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index 656770ad9..292de4c3a 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -76,6 +76,10 @@ class Site { $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); + $pub_incl = escape_tags(trim($_POST['pub_incl'])); + $pub_excl = escape_tags(trim($_POST['pub_excl'])); + + $permissions_role = escape_tags(trim($_POST['permissions_role'])); $techlevel = null; if(array_key_exists('techlevel', $_POST)) @@ -102,6 +106,9 @@ class Site { set_config('system', 'from_email_name' , $from_email_name); set_config('system', 'imagick_convert_path' , $imagick_path); set_config('system', 'thumbnail_security' , $thumbnail_security); + set_config('system', 'default_permissions_role', $permissions_role); + set_config('system', 'pubstream_incl',$pub_incl); + set_config('system', 'pubstream_excl',$pub_excl); set_config('system', 'techlevel_lock', $techlevel_lock); @@ -286,6 +293,12 @@ class Site { '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'); + + $role = array('permissions_role' , t('Default permission role for new accounts'), $default_role, t('This role will be used for the first channel created after registration.'),$perm_roles); + + $homelogin = get_config('system','login_on_homepage'); $enable_context_help = get_config('system','enable_context_help'); @@ -321,6 +334,7 @@ class Site { '$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), '$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.")), '$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.')), @@ -330,6 +344,10 @@ class Site { '$disable_discover_tab' => array('disable_discover_tab', t('Import Public Streams'), $discover_tab, t('Import and allow access to public content pulled from other sites. Warning: this content is unmoderated.')), '$site_firehose' => array('site_firehose', t('Site only Public Streams'), get_config('system','site_firehose'), t('Allow access to public content originating only from this site if Imported Public Streams are disabled.')), '$open_pubstream' => array('open_pubstream', t('Allow anybody on the internet to access the Public streams'), get_config('system','open_pubstream',1), t('Disable to require authentication before viewing. Warning: this content is unmoderated.')), + '$incl' => array('pub_incl',t('Only import Public stream posts with this text'), get_config('system','pubstream_incl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')), + '$excl' => array('pub_excl',t('Do not import Public stream posts with this text'), get_config('system','pubstream_excl'),t('words one per line or #tags or /patterns/ or lang=xx, leave blank to import all posts')), + + '$login_on_homepage' => array('login_on_homepage', t("Login on Homepage"),((intval($homelogin) || $homelogin === false) ? 1 : '') , t("Present a login box to visitors on the home page if no other content has been configured.")), '$enable_context_help' => array('enable_context_help', t("Enable context help"),((intval($enable_context_help) === 1 || $enable_context_help === false) ? 1 : 0) , t("Display contextual help for the current page when the help button is pressed.")), @@ -353,7 +371,7 @@ class Site { '$active_expire_days' => array('active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), ''), '$sellpage' => array('site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root())), - '$first_page' => array('first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Recommend: profiles, go, or settings')), + '$first_page' => array('first_page', t('Page to display after creating a new channel'), get_config('system','workflow_channel_next','profiles'), t('Default: profiles')), '$location' => array('site_location', t('Optional: site location'), get_config('system','site_location',''), t('Region or country')), diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php index c672ea467..78c8d99ae 100644 --- a/Zotlabs/Module/Apps.php +++ b/Zotlabs/Module/Apps.php @@ -15,6 +15,8 @@ class Apps extends \Zotlabs\Web\Controller { else $mode = 'list'; + $available = ((argc() == 2 && argv(1) === 'available') ? true : false); + $_SESSION['return_url'] = \App::$query_string; $apps = array(); @@ -23,7 +25,7 @@ class Apps extends \Zotlabs\Web\Controller { Zlib\Apps::import_system_apps(); $syslist = array(); $cat = ((array_key_exists('cat',$_GET) && $_GET['cat']) ? [ escape_tags($_GET['cat']) ] : ''); - $list = Zlib\Apps::app_list(local_channel(), (($mode == 'edit') ? true : false), $cat); + $list = Zlib\Apps::app_list((($available) ? 0 : local_channel()), (($mode == 'edit') ? true : false), $cat); if($list) { foreach($list as $x) { $syslist[] = Zlib\Apps::app_encode($x); @@ -39,7 +41,7 @@ class Apps extends \Zotlabs\Web\Controller { // logger('apps: ' . print_r($syslist,true)); foreach($syslist as $app) { - $apps[] = Zlib\Apps::app_render($app,$mode); + $apps[] = Zlib\Apps::app_render($app,(($available) ? 'install' : $mode)); } return replace_macros(get_markup_template('myapps.tpl'), array( @@ -48,7 +50,7 @@ class Apps extends \Zotlabs\Web\Controller { '$title' => t('Apps'), '$apps' => $apps, '$authed' => ((local_channel()) ? true : false), - '$manage' => t('Manage apps'), + '$manage' => (($available) ? '' : t('Manage apps')), '$create' => (($mode == 'edit') ? t('Create new app') : '') )); diff --git a/Zotlabs/Module/Article_edit.php b/Zotlabs/Module/Article_edit.php index 758c1db2e..89abccc40 100644 --- a/Zotlabs/Module/Article_edit.php +++ b/Zotlabs/Module/Article_edit.php @@ -128,6 +128,7 @@ class Article_edit extends \Zotlabs\Web\Controller { '$title' => t('Edit Article'), '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), '$id' => $itm[0]['id'], + '$cancel' => t('Cancel'), '$editor' => $editor )); diff --git a/Zotlabs/Module/Card_edit.php b/Zotlabs/Module/Card_edit.php index 7cc563fd2..694bdc4ea 100644 --- a/Zotlabs/Module/Card_edit.php +++ b/Zotlabs/Module/Card_edit.php @@ -128,6 +128,7 @@ class Card_edit extends \Zotlabs\Web\Controller { '$title' => t('Edit Card'), '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), '$id' => $itm[0]['id'], + '$cancel' => t('Cancel'), '$editor' => $editor )); diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index b9924c7f7..b5e6b3aee 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -18,6 +18,9 @@ class Channel extends \Zotlabs\Web\Controller { function init() { + if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?'])) + goaway('search' . '?f=&search=' . $_GET['search']); + $which = null; if(argc() > 1) $which = argv(1); @@ -82,7 +85,9 @@ class Channel extends \Zotlabs\Web\Controller { $category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : ''); $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : ''); + $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'post'); $static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0); + $search = ((x($_GET,'search')) ? $_GET['search'] : EMPTY_STR); $groups = array(); @@ -118,9 +123,12 @@ class Channel extends \Zotlabs\Web\Controller { $static = channel_manual_conv_update(\App::$profile['profile_uid']); - //$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']); - - // $o .= common_friends_visitor_widget(\App::$profile['profile_uid']); + // search terms header + if($search) { + $o .= replace_macros(get_markup_template("section_title.tpl"),array( + '$title' => t('Search Results For:') . ' ' . htmlspecialchars($search, ENT_COMPAT,'UTF-8') + )); + } if($channel && $is_owner) { $channel_acl = array( @@ -152,7 +160,8 @@ class Channel extends \Zotlabs\Web\Controller { 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true, - 'jotnets' => true + 'jotnets' => true, + 'reset' => t('Reset form') ); $o .= status_editor($a,$x); @@ -178,6 +187,19 @@ class Channel extends \Zotlabs\Web\Controller { $simple_update = (($update) ? " AND item_unseen = 1 " : ''); + if($search) { + $search = escape_tags($search); + if(strpos($search,'#') === 0) { + $sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG); + } + else { + $sql_extra .= sprintf(" AND item.body like '%s' ", + dbesc(protect_sprintf('%' . $search . '%')) + ); + } + } + + head_add_link([ 'rel' => 'alternate', 'type' => 'application/json+oembed', @@ -228,11 +250,22 @@ class Channel extends \Zotlabs\Web\Controller { 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 "; + } + + if($order === 'post') + $ordering = "created"; + else + $ordering = "commented"; + + $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'])); @@ -249,13 +282,13 @@ class Channel extends \Zotlabs\Web\Controller { } } else { - $r = q("SELECT item.parent AS item_id FROM item + $r = q("SELECT DISTINCT item.parent AS item_id, $ordering FROM item left join abook on ( item.author_xchan = abook.abook_xchan $abook_uids ) - WHERE true and item.uid = %d AND item.item_thread_top = 1 $item_normal + WHERE true and item.uid = %d $item_normal AND (abook.abook_blocked = 0 or abook.abook_flags is null) - AND item.item_wall = 1 - $sql_extra $sql_extra2 - ORDER BY created DESC, id $pager_sql ", + 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']) ); } @@ -264,7 +297,6 @@ class Channel extends \Zotlabs\Web\Controller { $r = array(); } } - if($r) { $parents_str = ids_to_querystr($r,'item_id'); @@ -280,7 +312,7 @@ class Channel extends \Zotlabs\Web\Controller { xchan_query($items); $items = fetch_post_tags($items, true); - $items = conv_sort($items,'created'); + $items = conv_sort($items,$ordering); if($load && $mid && (! count($items))) { // This will happen if we don't have sufficient permissions @@ -323,9 +355,9 @@ class Channel extends \Zotlabs\Web\Controller { '$fh' => '0', '$static' => $static, '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), - '$search' => '', + '$search' => $search, '$xchan' => '', - '$order' => '', + '$order' => $order, '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$file' => '', '$cats' => (($category) ? urlencode($category) : ''), @@ -371,12 +403,13 @@ class Channel extends \Zotlabs\Web\Controller { } } + $mode = (($search) ? 'search' : 'channel'); if($checkjs->disabled()) { - $o .= conversation($items,'channel',$update,'traditional'); + $o .= conversation($items,$mode,$update,'traditional'); } else { - $o .= conversation($items,'channel',$update,$page_mode); + $o .= conversation($items,$mode,$update,$page_mode); } if((! $update) || ($checkjs->disabled())) { diff --git a/Zotlabs/Module/Chatsvc.php b/Zotlabs/Module/Chatsvc.php index b4657e84d..d6708d95c 100644 --- a/Zotlabs/Module/Chatsvc.php +++ b/Zotlabs/Module/Chatsvc.php @@ -119,10 +119,10 @@ class Chatsvc extends \Zotlabs\Web\Controller { $rv['xchan_network'] = 'unknown'; $rv['xchan_url'] = z_root(); $rv['xchan_hidden'] = 1; - $rv['xchan_photo_mimetype'] = 'image/jpeg'; - $rv['xchan_photo_l'] = get_default_profile_photo(300); - $rv['xchan_photo_m'] = get_default_profile_photo(80); - $rv['xchan_photo_s'] = get_default_profile_photo(48); + $rv['xchan_photo_mimetype'] = 'image/png'; + $rv['xchan_photo_l'] = z_root() . '/' . get_default_profile_photo(300); + $rv['xchan_photo_m'] = z_root() . '/' . get_default_profile_photo(80); + $rv['xchan_photo_s'] = z_root() . '/' . get_default_profile_photo(48); } diff --git a/Zotlabs/Module/Cloud.php b/Zotlabs/Module/Cloud.php index 34397d275..1b330ecba 100644 --- a/Zotlabs/Module/Cloud.php +++ b/Zotlabs/Module/Cloud.php @@ -35,11 +35,20 @@ class Cloud extends \Zotlabs\Web\Controller { if (argc() > 1) $which = argv(1); + + if (argc() < 2 && intval(get_config('system','cloud_disable_siteroot'))) { + notice( t('Permission denied.') . EOL); + construct_page(); + killme(); + } + $profile = 0; if ($which) profile_load( $which, $profile); + + $auth = new \Zotlabs\Storage\BasicAuth(); $ob_hash = get_observer_hash(); diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php index 76e80156c..b911ac991 100644 --- a/Zotlabs/Module/Cover_photo.php +++ b/Zotlabs/Module/Cover_photo.php @@ -9,6 +9,7 @@ namespace Zotlabs\Module; require_once('include/photo/photo_driver.php'); require_once('include/channel.php'); +require_once('include/photos.php'); @@ -84,10 +85,41 @@ class Cover_photo extends \Zotlabs\Web\Controller { ); if($r) { - - $base_image = $r[0]; - $base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content'])); - + + $max_thumb = intval(get_config('system','max_thumbnail',1600)); + $iscaled = false; + if(intval($r[0]['height']) > $max_thumb || intval($r[0]['width']) > $max_thumb) { + $imagick_path = get_config('system','imagick_convert_path'); + if($imagick_path && @file_exists($imagick_path) && intval($r[0]['os_storage'])) { + + $fname = dbunescbin($r[0]['content']); + $tmp_name = $fname . '-001'; + $newsize = photo_calculate_scale(array_merge(getimagesize($fname),['max' => $max_thumb])); + $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $fname) . ' -resize ' . $newsize . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmp_name); + // logger('imagick thumbnail command: ' . $cmd); + for($x = 0; $x < 4; $x ++) { + exec($cmd); + if(file_exists($tmp_name)) { + break; + } + } + if(file_exists($tmp_name)) { + $base_image = $r[0]; + $gis = getimagesize($tmp_name); +logger('gis: ' . print_r($gis,true)); + $base_image['width'] = $gis[0]; + $base_image['height'] = $gis[1]; + $base_image['content'] = @file_get_contents($tmp_name); + $iscaled = true; + @unlink($tmp_name); + } + } + } + if(! $iscaled) { + $base_image = $r[0]; + $base_image['content'] = (($r[0]['os_storage']) ? @file_get_contents(dbunescbin($base_image['content'])) : dbunescbin($base_image['content'])); + } + $im = photo_factory($base_image['content'], $base_image['mimetype']); if($im->is_valid()) { @@ -119,10 +151,10 @@ class Cover_photo extends \Zotlabs\Web\Controller { intval(local_channel()) ); - $orig_srcx = ( $r[0]['width'] / $scaled_width ) * $srcX; - $orig_srcy = ( $r[0]['height'] / $scaled_height ) * $srcY; - $orig_srcw = ( $srcW / $scaled_width ) * $r[0]['width']; - $orig_srch = ( $srcH / $scaled_height ) * $r[0]['height']; + $orig_srcx = ( $base_image['width'] / $scaled_width ) * $srcX; + $orig_srcy = ( $base_image['height'] / $scaled_height ) * $srcY; + $orig_srcw = ( $srcW / $scaled_width ) * $base_image['width']; + $orig_srch = ( $srcH / $scaled_height ) * $base_image['height']; $im->cropImageRect(1200,435,$orig_srcx, $orig_srcy, $orig_srcw, $orig_srch); diff --git a/Zotlabs/Module/Dirsearch.php b/Zotlabs/Module/Dirsearch.php index 08f1f7a13..81942860f 100644 --- a/Zotlabs/Module/Dirsearch.php +++ b/Zotlabs/Module/Dirsearch.php @@ -257,7 +257,7 @@ class Dirsearch extends \Zotlabs\Web\Controller { else { $r = q("SELECT xchan.*, xprof.* from xchan left join xprof on xchan_hash = xprof_hash - where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot' and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 + where ( $logic $sql_extra ) $hub_query and xchan_network = 'zot' and xchan_system = 0 and xchan_hidden = 0 and xchan_orphan = 0 and xchan_deleted = 0 $safesql $order $qlimit " ); diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index a5bcf31dc..fe0408c6f 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -67,8 +67,7 @@ class Display extends \Zotlabs\Web\Controller { 'default_location' => $channel['channel_location'], 'nickname' => $channel['channel_address'], 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - - 'acl' => populate_acl($channel_acl), + 'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'permissions' => $channel_acl, 'bang' => '', 'visitor' => true, @@ -78,7 +77,8 @@ class Display extends \Zotlabs\Web\Controller { 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true, - 'jotnets' => true + 'jotnets' => true, + 'reset' => t('Reset form') ); $o = '<div id="jot-popup">'; diff --git a/Zotlabs/Module/Editblock.php b/Zotlabs/Module/Editblock.php index 8a7e87a09..563ad9ca2 100644 --- a/Zotlabs/Module/Editblock.php +++ b/Zotlabs/Module/Editblock.php @@ -138,6 +138,7 @@ class Editblock extends \Zotlabs\Web\Controller { '$title' => t('Edit Block'), '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), '$id' => $itm[0]['id'], + '$cancel' => t('Cancel'), '$editor' => $editor )); diff --git a/Zotlabs/Module/Editlayout.php b/Zotlabs/Module/Editlayout.php index 3d6a79507..67e0bcd32 100644 --- a/Zotlabs/Module/Editlayout.php +++ b/Zotlabs/Module/Editlayout.php @@ -137,6 +137,7 @@ class Editlayout extends \Zotlabs\Web\Controller { '$title' => t('Edit Layout'), '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), '$id' => $itm[0]['id'], + '$cancel' => t('Cancel'), '$editor' => $editor )); diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php index 57a4cb97f..45d8e7644 100644 --- a/Zotlabs/Module/Editpost.php +++ b/Zotlabs/Module/Editpost.php @@ -106,6 +106,7 @@ class Editpost extends \Zotlabs\Web\Controller { $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit post'), + '$cancel' => t('Cancel'), '$editor' => $editor )); diff --git a/Zotlabs/Module/Editwebpage.php b/Zotlabs/Module/Editwebpage.php index da536a729..b67421cd5 100644 --- a/Zotlabs/Module/Editwebpage.php +++ b/Zotlabs/Module/Editwebpage.php @@ -166,6 +166,7 @@ class Editwebpage extends \Zotlabs\Web\Controller { '$title' => t('Edit Webpage'), '$delete' => ((($itm[0]['author_xchan'] === $ob_hash) || ($itm[0]['owner_xchan'] === $ob_hash)) ? t('Delete') : false), '$editor' => $editor, + '$cancel' => t('Cancel'), '$id' => $itm[0]['id'] )); diff --git a/Zotlabs/Module/Filestorage.php b/Zotlabs/Module/Filestorage.php index 5c8557e5a..cd9ab601d 100644 --- a/Zotlabs/Module/Filestorage.php +++ b/Zotlabs/Module/Filestorage.php @@ -66,7 +66,7 @@ class Filestorage extends \Zotlabs\Web\Controller { $perms = get_all_perms($owner, $ob_hash); - if(! $perms['view_storage']) { + if(! ($perms['view_storage'] || is_site_admin())){ notice( t('Permission denied.') . EOL); return; } @@ -75,15 +75,29 @@ class Filestorage extends \Zotlabs\Web\Controller { // need to return for anyone other than the owner, despite the perms check for now. $is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false); - if(! $is_owner) { + if(! ($is_owner || is_site_admin())){ info( t('Permission Denied.') . EOL ); return; } if(argc() > 3 && argv(3) === 'delete') { + + if(argc() > 4 && argv(4) === 'json') + $json_return = true; + + + $admin_delete = false; + if(! $perms['write_storage']) { - notice( t('Permission denied.') . EOL); - return; + if(is_site_admin()) { + $admin_delete = true; + } + else { + notice( t('Permission denied.') . EOL); + if($json_return) + json_return_and_die([ 'success' => false ]); + return; + } } $file = intval(argv(2)); @@ -92,22 +106,31 @@ class Filestorage extends \Zotlabs\Web\Controller { intval($owner) ); if(! $r) { + if($json_return) + json_return_and_die([ 'success' => false ]); + notice( t('File not found.') . EOL); goaway(z_root() . '/cloud/' . $which); } $f = $r[0]; - $channel = \App::get_channel(); + + $channel = channelx_by_n($owner); $url = get_cloud_url($channel['channel_id'], $channel['channel_address'], $f['hash']); attach_delete($owner, $f['hash']); - $sync = attach_export_data($channel, $f['hash'], true); - if($sync) { - build_sync_packet($channel['channel_id'], array('file' => array($sync))); + if(! $admin_delete) { + $sync = attach_export_data($channel, $f['hash'], true); + if($sync) { + build_sync_packet($channel['channel_id'], array('file' => array($sync))); + } } + if(json_return) + json_return_and_die([ 'success' => true ]); + goaway(dirname($url)); } diff --git a/Zotlabs/Module/Group.php b/Zotlabs/Module/Group.php index 93a089d02..acebe995d 100644 --- a/Zotlabs/Module/Group.php +++ b/Zotlabs/Module/Group.php @@ -7,6 +7,17 @@ require_once('include/group.php'); class Group extends \Zotlabs\Web\Controller { + function init() { + if(! local_channel()) { + notice( t('Permission denied.') . EOL); + return; + } + + \App::$profile_uid = local_channel(); + + nav_set_selected('Privacy Groups'); + } + function post() { if(! local_channel()) { @@ -22,12 +33,10 @@ class Group extends \Zotlabs\Web\Controller { $r = group_add(local_channel(),$name,$public); if($r) { info( t('Privacy group created.') . EOL ); - $r = group_byname(local_channel(),$name); - if($r) - goaway(z_root() . '/group/' . $r); } - else - notice( t('Could not create privacy group.') . EOL ); + else { + notice( t('Could not create privacy group.') . EOL ); + } goaway(z_root() . '/group'); } @@ -74,30 +83,59 @@ class Group extends \Zotlabs\Web\Controller { notice( t('Permission denied') . EOL); return; } - + // 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) $switchtotext = get_config('system','groupedit_image_limit'); if($switchtotext === false) $switchtotext = 400; - - $tpl = get_markup_template('group_edit.tpl'); - $context = array('$submit' => t('Submit')); - - if((argc() == 2) && (argv(1) === 'new')) { - - return replace_macros($tpl, $context + array( - '$title' => t('Create a group of channels.'), - '$gname' => array('groupname',t('Privacy group name: '), '', ''), - '$gid' => 'new', - '$public' => array('public',t('Members are visible to other channels'), false, ''), + + + if((argc() == 1) || ((argc() == 2) && (argv(1) === 'new'))) { + + $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", + intval(local_channel()) + ); + + $i = 0; + foreach($groups as $group) { + $entries[$i]['name'] = $group['gname']; + $entries[$i]['id'] = $group['id']; + $entries[$i]['count'] = count(group_get_members($group['id'])); + $i++; + } + + $tpl = get_markup_template('privacy_groups.tpl'); + $o = replace_macros($tpl, [ + '$title' => t('Privacy Groups'), + '$add_new_label' => t('Add Group'), + '$new' => $new, + + // new group form + '$gname' => array('groupname',t('Privacy group name')), + '$public' => array('public',t('Members are visible to other channels'), false), '$form_security_token' => get_form_security_token("group_edit"), - )); - - + '$submit' => t('Submit'), + + // groups list + '$title' => t('Privacy Groups'), + '$name_label' => t('Name'), + '$count_label' => t('Members'), + '$entries' => $entries + ]); + + return $o; + } + + + + + $context = array('$submit' => t('Submit')); + $tpl = get_markup_template('group_edit.tpl'); if((argc() == 3) && (argv(1) === 'drop')) { check_form_security_token_redirectOnErr('/group', 'group_drop', 't'); @@ -172,22 +210,17 @@ class Group extends \Zotlabs\Web\Controller { $preselected[] = $member['xchan_hash']; } } - - $drop_tpl = get_markup_template('group_drop.tpl'); - $drop_txt = replace_macros($drop_tpl, array( - '$id' => $group['id'], - '$delete' => t('Delete'), - '$form_security_token' => get_form_security_token("group_drop"), - )); - - + $context = $context + array( - '$title' => t('Privacy group editor'), + '$title' => sprintf(t('Privacy Group: %s'), $group['gname']), + '$details_label' => t('Edit'), '$gname' => array('groupname',t('Privacy group name: '),$group['gname'], ''), '$gid' => $group['id'], '$drop' => $drop_txt, '$public' => array('public',t('Members are visible to other channels'), $group['visible'], ''), - '$form_security_token' => get_form_security_token('group_edit'), + '$form_security_token_edit' => get_form_security_token('group_edit'), + '$delete' => t('Delete Group'), + '$form_security_token_drop' => get_form_security_token("group_drop"), ); } @@ -196,14 +229,14 @@ class Group extends \Zotlabs\Web\Controller { return; $groupeditor = array( - 'label_members' => t('Members'), + 'label_members' => t('Group members'), 'members' => array(), - 'label_contacts' => t('All Connected Channels'), + 'label_contacts' => t('Not in this group'), 'contacts' => array(), ); $sec_token = addslashes(get_form_security_token('group_member_change')); - $textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : false); + $textmode = (($switchtotext && (count($members) > $switchtotext)) ? true : 'card'); foreach($members as $member) { if($member['xchan_url']) { $member['archived'] = (intval($member['abook_archived']) ? true : false); @@ -219,7 +252,7 @@ class Group extends \Zotlabs\Web\Controller { ); if(count($r)) { - $textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : false); + $textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : 'card'); foreach($r as $member) { if(! in_array($member['xchan_hash'],$preselected)) { $member['archived'] = (intval($member['abook_archived']) ? true : false); @@ -230,7 +263,7 @@ class Group extends \Zotlabs\Web\Controller { } $context['$groupeditor'] = $groupeditor; - $context['$desc'] = t('Click on a channel to add or remove.'); + $context['$desc'] = t('Click a channel to toggle membership'); if($change) { $tpl = get_markup_template('groupeditor.tpl'); diff --git a/Zotlabs/Module/Home.php b/Zotlabs/Module/Home.php index 79449c3b2..647a6412a 100644 --- a/Zotlabs/Module/Home.php +++ b/Zotlabs/Module/Home.php @@ -9,7 +9,7 @@ require_once('include/conversation.php'); class Home extends \Zotlabs\Web\Controller { function init() { - + $ret = array(); call_hooks('home_init',$ret); @@ -89,11 +89,11 @@ class Home extends \Zotlabs\Web\Controller { $sitename = get_config('system','sitename'); if($sitename) - $o .= '<h1 class="home-welcome">' . sprintf( t("Welcome to %s") ,$sitename) . '</h1>'; + $o .= '<h1 class="home-welcome">' . sprintf( t('Welcome to %s') ,$sitename) . '</h1>'; $loginbox = get_config('system','login_on_homepage'); if(intval($loginbox) || $loginbox === false) - $o .= login((\App::$config['system']['register_policy'] == REGISTER_CLOSED) ? 0 : 1); + $o .= login(true); return $o; diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index baeba82e8..fee4246c0 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -120,8 +120,7 @@ class Hq extends \Zotlabs\Web\Controller { 'default_location' => $channel['channel_location'], 'nickname' => $channel['channel_address'], 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - - 'acl' => populate_acl($channel_acl), + 'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'permissions' => $channel_acl, 'bang' => '', 'visitor' => true, @@ -131,7 +130,8 @@ class Hq extends \Zotlabs\Web\Controller { 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true, - 'jotnets' => true + 'jotnets' => true, + 'reset' => t('Reset form') ]; $o = replace_macros(get_markup_template("hq.tpl"), diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php index c36e4723a..d031bf16b 100644 --- a/Zotlabs/Module/Import.php +++ b/Zotlabs/Module/Import.php @@ -6,6 +6,7 @@ require_once('include/zot.php'); require_once('include/channel.php'); require_once('include/import.php'); require_once('include/perm_upgrade.php'); +require_once('library/urlify/URLify.php'); /** @@ -38,6 +39,7 @@ class Import extends \Zotlabs\Web\Controller { $filename = basename($_FILES['filename']['name']); $filesize = intval($_FILES['filename']['size']); $filetype = $_FILES['filename']['type']; + $newname = trim(strtolower($_REQUEST['newname'])); // import channel from file if($src) { @@ -146,7 +148,20 @@ class Import extends \Zotlabs\Web\Controller { } } - $channel = import_channel($data['channel'], $account_id, $seize); + if($newname) { + $x = false; + + if(get_config('system','unicode_usernames')) { + $x = punify(mb_strtolower($newname)); + } + + if((! $x) || strlen($x) > 64) { + $x = strtolower(\URLify::transliterate($newname)); + } + $newname = $x; + } + + $channel = import_channel($data['channel'], $account_id, $seize, $newname); } else { $moving = false; @@ -542,6 +557,7 @@ class Import extends \Zotlabs\Web\Controller { '$make_primary' => [ 'make_primary', t('Make this hub my primary location'), false, '', [ t('No'), t('Yes') ] ], '$moving' => [ 'moving', t('Move this channel (disable all previous locations)'), false, '', [ t('No'), t('Yes') ] ], + '$newname' => [ 'newname', t('Use this channel nickname instead of the one provided'), '', t('Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site.')], '$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'), diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php index 0bcd1c1fa..359f99b3e 100644 --- a/Zotlabs/Module/Invite.php +++ b/Zotlabs/Module/Invite.php @@ -113,7 +113,7 @@ class Invite extends \Zotlabs\Web\Controller { $invite_code = autoname(8) . rand(1000,9999); $nmessage = str_replace('$invite_code',$invite_code,$message); - $r = q("INSERT INTO register (hash,created) VALUES ('%s', '%s') ", + $r = q("INSERT INTO register (hash,created,uid,password,lang) VALUES ('%s', '%s',0,'','') ", dbesc($invite_code), dbesc(datetime_convert()) ); diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index bba1dc02d..ef1eb3700 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -528,22 +528,12 @@ class Item extends \Zotlabs\Web\Controller { // and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.) // we may need virtual or template classes to implement the possible alternatives - // If we're sending a private top-level message with a single @-taggable channel as a recipient, @-tag it, if our pconfig is set. - - if((! $parent) && (get_pconfig($profile_uid,'system','tagifonlyrecip')) && (substr_count($str_contact_allow,'<') == 1) && ($str_group_allow == '') && ($str_contact_deny == '') && ($str_group_deny == '')) { - $x = q("select abook_id, abconfig.v from abook left join abconfig on abook_xchan = abconfig.xchan and abook_channel = abconfig.chan and cat= 'their_perms' and abconfig.k = 'tag_deliver' and abconfig.v = 1 and abook_xchan = '%s' and abook_channel = %d limit 1", - dbesc(str_replace(array('<','>'),array('',''),$str_contact_allow)), - intval($profile_uid) - ); - if($x) - $body .= "\n\n@group+" . $x[0]['abook_id'] . "\n"; - } $body = cleanup_bbcode($body); // 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 @@ -1084,24 +1074,36 @@ class Item extends \Zotlabs\Web\Controller { if((argc() == 3) && (argv(1) === 'drop') && intval(argv(2))) { require_once('include/items.php'); - $i = q("select id, uid, author_xchan, owner_xchan, source_xchan, item_type from item where id = %d limit 1", + + + $i = q("select id, uid, item_origin, author_xchan, owner_xchan, source_xchan, item_type from item where id = %d limit 1", intval(argv(2)) ); if($i) { $can_delete = false; $local_delete = false; - if(local_channel() && local_channel() == $i[0]['uid']) + + if(local_channel() && local_channel() == $i[0]['uid']) { $local_delete = true; - - $sys = get_sys_channel(); - if(is_site_admin() && $sys['channel_id'] == $i[0]['uid']) - $can_delete = true; + } $ob_hash = get_observer_hash(); - if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) + if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) { $can_delete = true; - + } + + // The site admin can delete any post/item on the site. + // If the item originated on this site+channel the deletion will propagate downstream. + // Otherwise just the local copy is removed. + + if(is_site_admin()) { + $local_delete = true; + if(intval($i[0]['item_origin'])) + $can_delete = true; + } + + if(! ($can_delete || $local_delete)) { notice( t('Permission denied.') . EOL); return; diff --git a/Zotlabs/Module/Linkinfo.php b/Zotlabs/Module/Linkinfo.php index 3392e4114..f0d62b5e0 100644 --- a/Zotlabs/Module/Linkinfo.php +++ b/Zotlabs/Module/Linkinfo.php @@ -55,10 +55,10 @@ class Linkinfo extends \Zotlabs\Web\Controller { $h = explode("\n",$result['header']); foreach ($h as $l) { list($k,$v) = array_map("trim", explode(":", trim($l), 2)); - $hdrs[$k] = $v; + $hdrs[strtolower($k)] = $v; } - if (array_key_exists('Content-Type', $hdrs)) - $type = $hdrs['Content-Type']; + if (array_key_exists('content-type', $hdrs)) + $type = $hdrs['content-type']; if($type) { $zrl = is_matrix_url($url); if(stripos($type,'image/') !== false) { @@ -82,6 +82,10 @@ class Linkinfo extends \Zotlabs\Web\Controller { echo $br . '[audio]' . $url . '[/audio]' . $br; killme(); } + if(strtolower($type) === 'application/pdf' || strtolower($type) === 'application/x-pdf') { + echo $br . '[embed]' . $url . '[/embed]' . $br; + killme(); + } } } diff --git a/Zotlabs/Module/Login.php b/Zotlabs/Module/Login.php index ae35b922f..6430939b4 100644 --- a/Zotlabs/Module/Login.php +++ b/Zotlabs/Module/Login.php @@ -10,7 +10,7 @@ class Login extends \Zotlabs\Web\Controller { if(remote_channel() && $_SESSION['atoken']) goaway(z_root()); - return login((\App::$config['system']['register_policy'] == REGISTER_CLOSED) ? false : true); + return login(true); } } diff --git a/Zotlabs/Module/Magic.php b/Zotlabs/Module/Magic.php index 562b7687f..be6866592 100644 --- a/Zotlabs/Module/Magic.php +++ b/Zotlabs/Module/Magic.php @@ -24,8 +24,6 @@ class Magic extends \Zotlabs\Web\Controller { if($bdest) $dest = hex2bin($bdest); - $dest = html_entity_decode($dest); - $parsed = parse_url($dest); if(! $parsed) { if($test) { @@ -145,6 +143,9 @@ class Magic extends \Zotlabs\Web\Controller { if($owa) { + $dest = strip_zids($dest); + $dest = strip_query_param($dest,'f'); + $headers = []; $headers['Accept'] = 'application/x-zot+json' ; $headers['X-Open-Web-Auth'] = random_string(); 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/Menu.php b/Zotlabs/Module/Menu.php index 1dec65c1f..1687a4414 100644 --- a/Zotlabs/Module/Menu.php +++ b/Zotlabs/Module/Menu.php @@ -7,18 +7,36 @@ require_once('include/channel.php'); class Menu extends \Zotlabs\Web\Controller { + function init() { - if (array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { + + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { $sys = get_sys_channel(); - if ($sys && intval($sys['channel_id'])) { + if($sys && intval($sys['channel_id'])) { \App::$is_sys = true; } } + + if(argc() > 1) + $which = argv(1); + else + return; + + profile_load($which); + } + - function post() { + function post() { - $uid = local_channel(); + if(! \App::$profile) { + return; + } + + $which = argv(1); + + + $uid = \App::$profile['channel_id']; if(array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { $sys = get_sys_channel(); @@ -43,7 +61,7 @@ class Menu extends \Zotlabs\Web\Controller { if($r) { menu_sync_packet($uid,get_observer_hash(),$menu_id); //info( t('Menu updated.') . EOL); - goaway(z_root() . '/mitem/' . $menu_id . ((\App::$is_sys) ? '?f=&sys=1' : '')); + goaway(z_root() . '/mitem/' . $which . '/' . $menu_id . ((\App::$is_sys) ? '?f=&sys=1' : '')); } else notice( t('Unable to update menu.'). EOL); @@ -54,7 +72,7 @@ class Menu extends \Zotlabs\Web\Controller { menu_sync_packet($uid,get_observer_hash(),$r); //info( t('Menu created.') . EOL); - goaway(z_root() . '/mitem/' . $r . ((\App::$is_sys) ? '?f=&sys=1' : '')); + goaway(z_root() . '/mitem/' . $which . '/' . $r . ((\App::$is_sys) ? '?f=&sys=1' : '')); } else notice( t('Unable to create menu.'). EOL); @@ -67,27 +85,71 @@ class Menu extends \Zotlabs\Web\Controller { function get() { + + + if(! \App::$profile) { + notice( t('Requested profile is not available.') . EOL ); + \App::$error = 404; + return; + } + + $which = argv(1); + + $_SESSION['return_url'] = \App::$query_string; + $uid = local_channel(); - - if (\App::$is_sys && is_site_admin()) { + $owner = 0; + $channel = null; + $observer = \App::get_observer(); + + $channel = \App::get_channel(); + + if(\App::$is_sys && is_site_admin()) { $sys = get_sys_channel(); - $uid = intval($sys['channel_id']); + if($sys && intval($sys['channel_id'])) { + $uid = $owner = intval($sys['channel_id']); + $channel = $sys; + $observer = $sys; + } } - - if(! $uid) { + + if(! $owner) { + // Figure out who the page owner is. + $r = channelx_by_nick($which); + if($r) { + $owner = intval($r['channel_id']); + } + } + + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + + $perms = get_all_perms($owner,$ob_hash); + + if(! $perms['write_pages']) { notice( t('Permission denied.') . EOL); - return ''; + return; } + + // Get the observer, check their permissions + + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); + + $perms = get_all_perms($owner,$ob_hash); + + if(! $perms['write_pages']) { + notice( t('Permission denied.') . EOL); + return; + } + + if(argc() == 2) { - if(argc() == 1) { - - $channel = (($sys) ? $sys : \App::get_channel()); + $channel = (($sys) ? $sys : channelx_by_n($owner)); // list menus - $x = menu_list($uid); + $x = menu_list($owner); if($x) { for($y = 0; $y < count($x); $y ++) { - $m = menu_fetch($x[$y]['menu_name'],$uid,get_observer_hash()); + $m = menu_fetch($x[$y]['menu_name'],$owner,get_observer_hash()); if($m) $x[$y]['element'] = '[element]' . base64url_encode(json_encode(menu_element($channel,$m))) . '[/element]'; $x[$y]['bookmark'] = (($x[$y]['menu_flags'] & MENU_BOOKMARK) ? true : false); @@ -100,6 +162,7 @@ class Menu extends \Zotlabs\Web\Controller { '$menu_bookmark' => array('menu_bookmark', t('Allow Bookmarks'), 0 , t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))), '$submit' => t('Submit and proceed'), '$sys' => \App::$is_sys, + '$nick' => $which, '$display' => 'none' )); @@ -119,6 +182,7 @@ class Menu extends \Zotlabs\Web\Controller { '$hintdrop' => t('Delete this menu'), '$hintcontent' => t('Edit menu contents'), '$hintedit' => t('Edit this menu'), + '$nick' => $which, '$sys' => \App::$is_sys )); @@ -126,19 +190,19 @@ class Menu extends \Zotlabs\Web\Controller { } - if(argc() > 1) { - if(intval(argv(1))) { + if(argc() > 2) { + if(intval(argv(2))) { - if(argc() == 3 && argv(2) == 'drop') { - menu_sync_packet($uid,get_observer_hash(),intval(argv(1)),true); - $r = menu_delete_id(intval(argv(1)),$uid); + if(argc() == 4 && argv(3) == 'drop') { + menu_sync_packet($owner,get_observer_hash(),intval(argv(1)),true); + $r = menu_delete_id(intval(argv(2)),$owner); if(!$r) notice( t('Menu could not be deleted.'). EOL); - goaway(z_root() . '/menu' . ((\App::$is_sys) ? '?f=&sys=1' : '')); + goaway(z_root() . '/menu/' . $which . ((\App::$is_sys) ? '?f=&sys=1' : '')); } - $m = menu_fetch_id(intval(argv(1)),$uid); + $m = menu_fetch_id(intval(argv(2)),$owner); if(! $m) { notice( t('Menu not found.') . EOL); @@ -148,14 +212,15 @@ class Menu extends \Zotlabs\Web\Controller { $o = replace_macros(get_markup_template('menuedit.tpl'), array( '$header' => t('Edit Menu'), '$sys' => \App::$is_sys, - '$menu_id' => intval(argv(1)), - '$menu_edit_link' => 'mitem/' . intval(argv(1)) . ((\App::$is_sys) ? '?f=&sys=1' : ''), + '$menu_id' => intval(argv(2)), + '$menu_edit_link' => 'mitem/' . $which . '/' . intval(argv(1)) . ((\App::$is_sys) ? '?f=&sys=1' : ''), '$hintedit' => t('Add or remove entries to this menu'), '$editcontents' => t('Edit menu contents'), '$menu_name' => array('menu_name', t('Menu name'), $m['menu_name'], t('Must be unique, only seen by you'), '*'), '$menu_desc' => array('menu_desc', t('Menu title'), $m['menu_desc'], t('Menu title as seen by others'), ''), '$menu_bookmark' => array('menu_bookmark', t('Allow bookmarks'), (($m['menu_flags'] & MENU_BOOKMARK) ? 1 : 0), t('Menu may be used to store saved bookmarks'), array(t('No'), t('Yes'))), '$menu_system' => (($m['menu_flags'] & MENU_SYSTEM) ? 1 : 0), + '$nick' => $which, '$submit' => t('Submit and proceed') )); diff --git a/Zotlabs/Module/Mitem.php b/Zotlabs/Module/Mitem.php index 28f51b81b..ac7470e13 100644 --- a/Zotlabs/Module/Mitem.php +++ b/Zotlabs/Module/Mitem.php @@ -8,22 +8,25 @@ require_once('include/acl_selectors.php'); class Mitem extends \Zotlabs\Web\Controller { function init() { - - $uid = local_channel(); - - if(array_key_exists('sys',$_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { + + if(argc() > 1 && argv(1) === 'sys' && is_site_admin()) { $sys = get_sys_channel(); - $uid = intval($sys['channel_id']); - \App::$is_sys = true; + if($sys && intval($sys['channel_id'])) { + \App::$is_sys = true; + } } - - if(! $uid) + + if(argc() > 1) + $which = argv(1); + else return; + + profile_load($which); - if(argc() < 2) + if(argc() < 3) return; - $m = menu_fetch_id(intval(argv(1)),$uid); + $m = menu_fetch_id(intval(argv(2)),\App::$profile['channel_id']); if(! $m) { notice( t('Menu not found.') . EOL); return ''; @@ -32,19 +35,27 @@ class Mitem extends \Zotlabs\Web\Controller { } - function post() { + function post() { - $uid = local_channel(); + if(! \App::$profile) { + return; + } + + $which = argv(1); + + + $uid = \App::$profile['channel_id']; - if(\App::$is_sys && is_site_admin()) { + if(array_key_exists('sys', $_REQUEST) && $_REQUEST['sys'] && is_site_admin()) { $sys = get_sys_channel(); $uid = intval($sys['channel_id']); + \App::$is_sys = true; } - if(! $uid) { + if(! $uid) return; - } - + + if(! \App::$data['menu']) return; @@ -63,14 +74,14 @@ class Mitem extends \Zotlabs\Web\Controller { $_REQUEST['mitem_flags'] |= MENU_ITEM_NEWWIN; - $mitem_id = ((argc() > 2) ? intval(argv(2)) : 0); + $mitem_id = ((argc() > 3) ? intval(argv(3)) : 0); if($mitem_id) { $_REQUEST['mitem_id'] = $mitem_id; $r = menu_edit_item($_REQUEST['menu_id'],$uid,$_REQUEST); if($r) { menu_sync_packet($uid,get_observer_hash(),$_REQUEST['menu_id']); //info( t('Menu element updated.') . EOL); - goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : '')); + goaway(z_root() . '/mitem/' . $which . '/' . $_REQUEST['menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : '')); } else notice( t('Unable to update menu element.') . EOL); @@ -82,10 +93,10 @@ class Mitem extends \Zotlabs\Web\Controller { menu_sync_packet($uid,get_observer_hash(),$_REQUEST['menu_id']); //info( t('Menu element added.') . EOL); if($_REQUEST['submit']) { - goaway(z_root() . '/menu' . ((\App::$is_sys) ? '?f=&sys=1' : '')); + goaway(z_root() . '/menu/' . $which . ((\App::$is_sys) ? '?f=&sys=1' : '')); } if($_REQUEST['submit-more']) { - goaway(z_root() . '/mitem/' . $_REQUEST['menu_id'] . '?f=&display=block' . ((\App::$is_sys) ? '&sys=1' : '') ); + goaway(z_root() . '/mitem/' . $which . '/' . $_REQUEST['menu_id'] . '?f=&display=block' . ((\App::$is_sys) ? '&sys=1' : '') ); } } else @@ -96,12 +107,15 @@ class Mitem extends \Zotlabs\Web\Controller { } - function get() { + function get() { $uid = local_channel(); - $channel = \App::get_channel(); + $owner = \App::$profile['channel_id']; + $channel = channelx_by_n($owner); $observer = \App::get_observer(); - + + $which = argv(1); + $ob_hash = (($observer) ? $observer['xchan_hash'] : ''); if(\App::$is_sys && is_site_admin()) { @@ -116,15 +130,15 @@ class Mitem extends \Zotlabs\Web\Controller { return ''; } - if(argc() < 2 || (! \App::$data['menu'])) { + if(argc() < 3 || (! \App::$data['menu'])) { notice( t('Not found.') . EOL); return ''; } - $m = menu_fetch(\App::$data['menu']['menu_name'],$uid,$ob_hash); + $m = menu_fetch(\App::$data['menu']['menu_name'],$owner,$ob_hash); \App::$data['menu_item'] = $m; - $menu_list = menu_list($uid); + $menu_list = menu_list($owner); foreach($menu_list as $menus) { if($menus['menu_name'] != $m['menu']['menu_name']) @@ -135,10 +149,10 @@ class Mitem extends \Zotlabs\Web\Controller { $lockstate = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'); - if(argc() == 2) { + if(argc() == 3) { $r = q("select * from menu_item where mitem_menu_id = %d and mitem_channel_id = %d order by mitem_order asc, mitem_desc asc", intval(\App::$data['menu']['menu_id']), - intval($uid) + intval($owner) ); if($_GET['display']) { @@ -167,6 +181,7 @@ class Mitem extends \Zotlabs\Web\Controller { '$display' => $display, '$lockstate' => $lockstate, '$menu_names' => $menu_names, + '$nick' => $which, '$sys' => \App::$is_sys )); @@ -187,40 +202,41 @@ class Mitem extends \Zotlabs\Web\Controller { '$hintnew' => t('Add menu element'), '$hintdrop' => t('Delete this menu item'), '$hintedit' => t('Edit this menu item'), + '$nick' => $which, )); return $o; } - if(argc() > 2) { - - if(intval(argv(2))) { + if(argc() > 3) { + + if(intval(argv(3))) { $m = q("select * from menu_item where mitem_id = %d and mitem_channel_id = %d limit 1", - intval(argv(2)), - intval($uid) + intval(argv(3)), + intval($owner) ); if(! $m) { notice( t('Menu item not found.') . EOL); - goaway(z_root() . '/menu'. ((\App::$is_sys) ? '?f=&sys=1' : '')); + goaway(z_root() . '/menu/'. $which . ((\App::$is_sys) ? '?f=&sys=1' : '')); } $mitem = $m[0]; $lockstate = (($mitem['allow_cid'] || $mitem['allow_gid'] || $mitem['deny_cid'] || $mitem['deny_gid']) ? 'lock' : 'unlock'); - if(argc() == 4 && argv(3) == 'drop') { - menu_sync_packet($uid,get_observer_hash(),$mitem['mitem_menu_id']); - $r = menu_del_item($mitem['mitem_menu_id'], $uid, intval(argv(2))); - menu_sync_packet($uid,get_observer_hash(),$mitem['mitem_menu_id']); + if(argc() == 5 && argv(4) == 'drop') { + menu_sync_packet($owner,get_observer_hash(),$mitem['mitem_menu_id']); + $r = menu_del_item($mitem['mitem_menu_id'], $owner, intval(argv(3))); + menu_sync_packet($owner,get_observer_hash(),$mitem['mitem_menu_id']); if($r) info( t('Menu item deleted.') . EOL); else notice( t('Menu item could not be deleted.'). EOL); - goaway(z_root() . '/mitem/' . $mitem['mitem_menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : '')); + goaway(z_root() . '/mitem/' . $which . '/' . $mitem['mitem_menu_id'] . ((\App::$is_sys) ? '?f=&sys=1' : '')); } // edit menu item @@ -234,7 +250,7 @@ class Mitem extends \Zotlabs\Web\Controller { '$allow_gid' => acl2json($mitem['allow_gid']), '$deny_cid' => acl2json($mitem['deny_cid']), '$deny_gid' => acl2json($mitem['deny_gid']), - '$mitem_id' => intval(argv(2)), + '$mitem_id' => intval(argv(3)), '$mitem_desc' => array('mitem_desc', t('Link text'), $mitem['mitem_desc'], '','*'), '$mitem_link' => array('mitem_link', t('Link or Submenu Target'), $mitem['mitem_link'], 'Enter URL of the link or select a menu name to create a submenu', '*', 'list="menu-names"'), '$usezid' => array('usezid', t('Use magic-auth if available'), (($mitem['mitem_flags'] & MENU_ITEM_ZID) ? 1 : 0), '', array(t('No'), t('Yes'))), @@ -242,7 +258,8 @@ class Mitem extends \Zotlabs\Web\Controller { '$mitem_order' => array('mitem_order', t('Order in list'),$mitem['mitem_order'],t('Higher numbers will sink to bottom of listing')), '$submit' => t('Submit'), '$lockstate' => $lockstate, - '$menu_names' => $menu_names + '$menu_names' => $menu_names, + '$nick' => $which )); return $o; diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index edbcd2ea7..77a08585b 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -15,6 +15,9 @@ class Network extends \Zotlabs\Web\Controller { notice( t('Permission denied.') . EOL); return; } + + if(in_array(substr($_GET['search'],0,1),[ '@', '!', '?'])) + goaway('search' . '?f=&search=' . $_GET['search']); if(count($_GET) < 2) { $network_options = get_pconfig(local_channel(),'system','network_page_default'); @@ -57,13 +60,26 @@ class Network extends \Zotlabs\Web\Controller { $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']) : ''); - $nouveau = ((x($_GET,'new')) ? intval($_GET['new']) : 0); $static = ((x($_GET,'static')) ? intval($_GET['static']) : 0); $gid = ((x($_GET,'gid')) ? intval($_GET['gid']) : 0); $category = ((x($_REQUEST,'cat')) ? $_REQUEST['cat'] : ''); $hashtags = ((x($_REQUEST,'tag')) ? $_REQUEST['tag'] : ''); $verb = ((x($_REQUEST,'verb')) ? $_REQUEST['verb'] : ''); - + + + $order = get_pconfig(local_channel(), 'mod_network', 'order', 0); + switch($order) { + case 0: + $order = 'comment'; + break; + case 1: + $order = 'post'; + break; + case 2: + $nouveau = true; + break; + } + $search = (($_GET['search']) ? $_GET['search'] : ''); if($search) { $_GET['netsearch'] = escape_tags($search); @@ -84,7 +100,7 @@ class Network extends \Zotlabs\Web\Controller { } if($datequery) - $_GET['order'] = 'post'; + $order = 'post'; // filter by collection (e.g. group) @@ -110,12 +126,8 @@ class Network extends \Zotlabs\Web\Controller { $default_cmin = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmin',0) : (-1)); $default_cmax = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmax',99) : (-1)); - - // if no tabs are selected, defaults to comments - $cid = ((x($_GET,'cid')) ? intval($_GET['cid']) : 0); $star = ((x($_GET,'star')) ? intval($_GET['star']) : 0); - $order = ((x($_GET,'order')) ? notags($_GET['order']) : 'comment'); $liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0); $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0); $spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0); @@ -124,18 +136,21 @@ class Network extends \Zotlabs\Web\Controller { $file = ((x($_GET,'file')) ? $_GET['file'] : ''); $xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : ''); $net = ((x($_GET,'net')) ? $_GET['net'] : ''); + $pf = ((x($_GET,'pf')) ? $_GET['pf'] : ''); $deftag = ''; - if(x($_GET,'search') || x($_GET,'file')) + + if(x($_GET,'search') || $file || (!$pf && $cid)) $nouveau = true; if($cid) { - $r = q("SELECT abook_xchan FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1", + $cid_r = q("SELECT abook.abook_xchan, xchan.xchan_addr, xchan.xchan_name, xchan.xchan_url, xchan.xchan_photo_s, xchan.xchan_pubforum from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and abook_blocked = 0 limit 1", intval($cid), intval(local_channel()) ); - if(! $r) { + + if(! $cid_r) { if($update) { killme(); } @@ -143,14 +158,14 @@ class Network extends \Zotlabs\Web\Controller { goaway(z_root() . '/network'); // NOTREACHED } - if($_GET['pf'] === '1') - $deftag = '!' . t('forum') . '+' . intval($cid); + if($pf) + $deftag = '!{' . (($cid_r[0]['xchan_addr']) ? $cid_r[0]['xchan_addr'] : $cid_r[0]['xchan_url']) . '}'; else - $def_acl = [ 'allow_cid' => '<' . $r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; + $def_acl = [ 'allow_cid' => '<' . $cid_r[0]['abook_xchan'] . '>', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '' ]; } if(! $update) { - $tabs = network_tabs(); + $tabs = ''; //network_tabs(); $o .= $tabs; // search terms header @@ -185,7 +200,8 @@ class Network extends \Zotlabs\Web\Controller { 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true, - 'jotnets' => true + 'jotnets' => true, + 'reset' => t('Reset form') ); if($deftag) $x['pretext'] = $deftag; @@ -218,17 +234,16 @@ class Network extends \Zotlabs\Web\Controller { $contact_str = ''; $contacts = group_get_members($group); if($contacts) { - foreach($contacts as $c) { - if($contact_str) - $contact_str .= ','; - $contact_str .= "'" . $c['xchan'] . "'"; - } + $contact_str = ids_to_querystr($contacts,'xchan',true); } else { - $contact_str = ' 0 '; - info( t('Privacy group is empty')); + $contact_str = " '0' "; + if(! $update) { + info( t('Privacy group is empty')); + } } $item_thread_top = ''; + $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str )) or allow_gid like '" . protect_sprintf('%<' . dbesc($group_hash) . '>%') . "' ) and id = parent $item_normal ) "; $x = group_rec_byhash(local_channel(), $group_hash); @@ -244,27 +259,31 @@ class Network extends \Zotlabs\Web\Controller { $o .= $status_editor; } - - elseif($cid) { - - $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and abook_blocked = 0 limit 1", - intval($cid), - intval(local_channel()) - ); - if($r) { - $item_thread_top = ''; - $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) $item_normal ) "; - $title = replace_macros(get_markup_template("section_title.tpl"),array( - '$title' => '<a href="' . zid($r[0]['xchan_url']) . '" ><img src="' . zid($r[0]['xchan_photo_s']) . '" alt="' . urlencode($r[0]['xchan_name']) . '" /></a> <a href="' . zid($r[0]['xchan_url']) . '" >' . $r[0]['xchan_name'] . '</a>' - )); - $o = $tabs; - $o .= $title; - $o .= $status_editor; - } - else { - notice( t('Invalid connection.') . EOL); - goaway(z_root() . '/network'); + elseif($cid_r) { + $item_thread_top = ''; + + if($load || $update) { + if(!$pf && $nouveau) { + $sql_extra = " AND author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' "; + } + else { + $ttype = (($pf) ? TERM_FORUM : TERM_MENTION); + + $p1 = q("SELECT DISTINCT parent FROM item WHERE uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' OR owner_xchan = '" . dbesc($cid_r[0]['abook_xchan']) . "' ) $item_normal "); + $p2 = q("SELECT oid AS parent FROM term WHERE uid = " . intval(local_channel()) . " AND ttype = $ttype AND term = '" . dbesc($cid_r[0]['xchan_name']) . "'"); + + $p_str = ids_to_querystr(array_merge($p1,$p2),'parent'); + $sql_extra = " AND item.parent IN ( $p_str ) "; + } } + + $title = replace_macros(get_markup_template("section_title.tpl"),array( + '$title' => '<a href="' . zid($cid_r[0]['xchan_url']) . '" ><img src="' . zid($cid_r[0]['xchan_photo_s']) . '" alt="' . urlencode($cid_r[0]['xchan_name']) . '" /></a> <a href="' . zid($cid_r[0]['xchan_url']) . '" >' . $cid_r[0]['xchan_name'] . '</a>' + )); + + $o = $tabs; + $o .= $title; + $o .= $status_editor; } elseif($xchan) { $r = q("select * from xchan where xchan_hash = '%s'", @@ -338,7 +357,8 @@ class Network extends \Zotlabs\Web\Controller { '$mid' => '', '$verb' => $verb, '$net' => $net, - '$dbegin' => $datequery2 + '$dbegin' => $datequery2, + '$pf' => (($pf) ? $pf : '0'), )); } @@ -378,9 +398,15 @@ class Network extends \Zotlabs\Web\Controller { if($conv) { $item_thread_top = ''; - $sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan like '%s' or item_mentionsme = 1 )) ", - dbesc(protect_sprintf($channel['channel_hash'])) - ); + + if($nouveau) { + $sql_extra .= " AND author_xchan = '" . dbesc($channel['channel_hash']) . "' "; + } + else { + $sql_extra .= sprintf(" AND parent IN (SELECT distinct(parent) from item where ( author_xchan = '%s' or item_mentionsme = 1 )) ", + dbesc(protect_sprintf($channel['channel_hash'])) + ); + } } if($update && ! $load) { @@ -454,7 +480,7 @@ class Network extends \Zotlabs\Web\Controller { if($nouveau && $load) { // "New Item View" - show all items unthreaded in reverse created date order - $items = q("SELECT item.*, item.id AS item_id, received FROM item + $items = q("SELECT item.*, item.id AS item_id, created FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query WHERE true $uids $item_normal @@ -462,7 +488,7 @@ class Network extends \Zotlabs\Web\Controller { $simple_update $sql_extra $sql_options $sql_nets $net_query2 - ORDER BY item.received DESC $pager_sql " + ORDER BY item.created DESC $pager_sql " ); require_once('include/items.php'); @@ -476,12 +502,11 @@ class Network extends \Zotlabs\Web\Controller { // Normal conversation view if($order === 'post') - $ordering = "created"; + $ordering = "created"; else - $ordering = "commented"; + $ordering = "commented"; if($load) { - // Fetch a page full of parent items for this page $r = q("SELECT item.parent AS item_id FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) @@ -562,6 +587,9 @@ class Network extends \Zotlabs\Web\Controller { } $mode = (($nouveau) ? 'network-new' : 'network'); + + if($search) + $mode = 'search'; $o .= conversation($items,$mode,$update,$page_mode); diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index d9becbc22..97a46a43e 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -41,7 +41,7 @@ class New_channel extends \Zotlabs\Web\Controller { $test[] = legal_webbie($x); // fullname plus random number $test[] = legal_webbie($x) . mt_rand(1000,9999); - + json_return_and_die(check_webbie($test)); } @@ -49,7 +49,10 @@ class New_channel extends \Zotlabs\Web\Controller { require_once('library/urlify/URLify.php'); $result = array('error' => false, 'message' => ''); $n = trim($_REQUEST['nick']); - + if(! $n) { + $n = trim($_REQUEST['name']); + } + $x = false; if(get_config('system','unicode_usernames')) { @@ -58,9 +61,20 @@ class New_channel extends \Zotlabs\Web\Controller { if((! $x) || strlen($x) > 64) $x = strtolower(\URLify::transliterate($n)); - + + $test = array(); + // first name + if(strpos($x,' ')) + $test[] = legal_webbie(substr($x,0,strpos($x,' '))); + if($test[0]) { + // first name plus first initial of last + $test[] = ((strpos($x,' ')) ? $test[0] . legal_webbie(trim(substr($x,strpos($x,' '),2))) : ''); + // first name plus random number + $test[] = $test[0] . mt_rand(1000,9999); + } + $n = legal_webbie($x); if(strlen($n)) { $test[] = $n; @@ -124,7 +138,7 @@ class New_channel extends \Zotlabs\Web\Controller { intval($aid) ); if($r && (! intval($r[0]['total']))) { - $default_role = get_config('system','default_permissions_role'); + $default_role = get_config('system','default_permissions_role','social'); } $limit = account_service_class_fetch(get_account_id(),'total_identities'); @@ -136,21 +150,35 @@ class New_channel extends \Zotlabs\Web\Controller { $channel_usage_message = ''; } } - + + $name_help = '<span id="name_help_loading" style="display:none">' . t('Loading') . '</span><span id="name_help_text">'; + $name_help .= (($default_role) + ? t('Your real name is recommended.') + : t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"') + ); + $name_help .= '</span>'; + + $nick_help = '<span id="nick_help_loading" style="display:none">' . t('Loading') . '</span><span id="nick_help_text">'; + $nick_help .= t('This will be used to create a unique network address (like an email address).'); + if(! get_config('system','unicode_usernames')) { + $nick_help .= ' ' . t('Allowed characters are a-z 0-9, - and _'); + } + $nick_help .= '<span>'; + $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('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"'), "*"); + $name = array('name', t('Channel name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), $name_help, "*"); $nickhub = '@' . \App::get_hostname(); - $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub), "*"); - $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel role with your privacy requirements.') . ' <a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about roles') . '</a>',$perm_roles); + $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), $nick_help, "*"); + $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role compatible with your usage needs and privacy requirements.') . '<br>' . '<a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles); $o = replace_macros(get_markup_template('new_channel.tpl'), array( - '$title' => t('Create Channel'), - '$desc' => t('A channel is a unique network identity. It can represent a person (social network profile), a forum (group), a business or celebrity page, a newsfeed, and many other things. Channels can make connections with other channels to share information with each other.') . ' ' . t('The type of channel you create affects the basic privacy settings, the permissions that are granted to connections/friends, and also the channel\'s visibility across the network.'), + '$title' => t('Create a Channel'), + '$desc' => t('A channel is a unique network identity. It can represent a person (social network profile), a forum (group), a business or celebrity page, a newsfeed, and many other things.') , '$label_import' => t('or <a href="import">import an existing channel</a> from another location.'), '$name' => $name, '$role' => $role, 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/Notifications.php b/Zotlabs/Module/Notifications.php index dfa007548..1762ad5f6 100644 --- a/Zotlabs/Module/Notifications.php +++ b/Zotlabs/Module/Notifications.php @@ -41,8 +41,6 @@ class Notifications extends \Zotlabs\Web\Controller { $notifications_available = 1; foreach ($r as $rr) { $x = strip_tags(bbcode($rr['msg'])); - if(strpos($x,',')) - $x = substr($x,strpos($x,',')+1); $notif_content .= replace_macros(get_markup_template('notify.tpl'),array( '$item_link' => z_root().'/notify/view/'. $rr['id'], '$item_image' => $rr['photo'], diff --git a/Zotlabs/Module/Oauthinfo.php b/Zotlabs/Module/Oauthinfo.php new file mode 100644 index 000000000..2d10913c4 --- /dev/null +++ b/Zotlabs/Module/Oauthinfo.php @@ -0,0 +1,23 @@ +<?php + +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', + '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/Photo.php b/Zotlabs/Module/Photo.php index b3171fe75..3f68e5c67 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -4,6 +4,7 @@ namespace Zotlabs\Module; require_once('include/security.php'); require_once('include/attach.php'); require_once('include/photo/photo_driver.php'); +require_once('include/photos.php'); class Photo extends \Zotlabs\Web\Controller { @@ -13,7 +14,8 @@ class Photo extends \Zotlabs\Web\Controller { $prvcachecontrol = false; $streaming = null; $channel = null; - + $person = 0; + switch(argc()) { case 4: $person = argv(3); @@ -30,8 +32,8 @@ class Photo extends \Zotlabs\Web\Controller { } $observer_xchan = get_observer_hash(); - - $default = get_default_profile_photo(); + + $default = z_root() . '/' . get_default_profile_photo(); if(isset($type)) { @@ -45,11 +47,11 @@ class Photo extends \Zotlabs\Web\Controller { case 'm': $resolution = 5; - $default = get_default_profile_photo(80); + $default = z_root() . '/' . get_default_profile_photo(80); break; case 's': $resolution = 6; - $default = get_default_profile_photo(48); + $default = z_root() . '/' . get_default_profile_photo(48); break; case 'l': default: @@ -83,7 +85,7 @@ class Photo extends \Zotlabs\Web\Controller { $data = file_get_contents($data); } if(! $data) { - $data = file_get_contents($default); + $data = fetch_image_from_url($default,$mimetype); } if(! $mimetype) { $mimetype = 'image/png'; @@ -144,6 +146,20 @@ class Photo extends \Zotlabs\Web\Controller { if(! in_array($resolution,[4,5,6])) $allowed = (-1); } + + if($allowed === (-1)) { + $allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo); + } + + if(intval($r[0]['photo_usage'])) { + $allowed = 1; + if(intval($r[0]['photo_usage']) === PHOTO_COVER) + if($resolution < PHOTO_RES_COVER_1200) + $allowed = (-1); + if(intval($r[0]['photo_usage']) === PHOTO_PROFILE) + if(! in_array($resolution,[4,5,6])) + $allowed = (-1); + } if($allowed === (-1)) $allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo); @@ -166,13 +182,12 @@ class Photo extends \Zotlabs\Web\Controller { } else { if(! $allowed) { - logger('mod_photo: forbidden. ' . \App::$query_string); - $observer = \App::get_observer(); - logger('mod_photo: observer = ' . (($observer) ? $observer['xchan_addr'] : '(not authenticated)')); - $data = file_get_contents('images/nosign.png'); - $mimetype = 'image/png'; - $prvcachecontrol = true; + http_status_exit(403,'forbidden'); } + if(! $exists) { + http_status_exit(404,'not found'); + } + } } } @@ -182,16 +197,13 @@ class Photo extends \Zotlabs\Web\Controller { switch($resolution) { case 4: - $data = file_get_contents(get_default_profile_photo()); - $mimetype = 'image/png'; + $data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(),$mimetype); break; case 5: - $data = file_get_contents(get_default_profile_photo(80)); - $mimetype = 'image/png'; + $data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(80),$mimetype); break; case 6: - $data = file_get_contents(get_default_profile_photo(48)); - $mimetype = 'image/png'; + $data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(48),$mimetype); break; default: killme(); diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index fceed1910..489bffc4a 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -102,14 +102,7 @@ class Photos extends \Zotlabs\Web\Controller { if($_REQUEST['dropalbum'] == t('Delete Album')) { - - // This is dangerous because we combined file storage and photos into one interface - // This function will remove all photos from any directory with the same name since - // we have not passed the path value. - - // The correct solution would be to use a full pathname from your storage root for 'album' - // We also need to prevent/block removing the storage root folder. - + $folder_hash = ''; $r = q("select * from attach where is_dir = 1 and uid = %d and hash = '%s'", @@ -124,7 +117,8 @@ class Photos extends \Zotlabs\Web\Controller { $res = array(); - + $admin_delete = false; + // get the list of photos we are about to delete if(remote_channel() && (! local_channel())) { @@ -133,6 +127,10 @@ class Photos extends \Zotlabs\Web\Controller { elseif(local_channel()) { $str = photos_album_get_db_idstr(local_channel(),$album); } + elseif(is_site_admin()) { + $str = photos_album_get_db_idstr_admin($page_owner_uid,$album); + $admin_delete = true; + } else { $str = null; } @@ -145,7 +143,7 @@ class Photos extends \Zotlabs\Web\Controller { ); if($r) { foreach($r as $i) { - attach_delete($page_owner_uid, $i['resource_id'], 1 ); + attach_delete($page_owner_uid, $i['resource_id'], true ); } } @@ -158,12 +156,14 @@ class Photos extends \Zotlabs\Web\Controller { // @FIXME do the same for the linked attach if($folder_hash) { - attach_delete($page_owner_uid,$folder_hash, 1); - - $sync = attach_export_data(\App::$data['channel'],$folder_hash, true); + attach_delete($page_owner_uid, $folder_hash, true ); + + if(! $admin_delete) { + $sync = attach_export_data(\App::$data['channel'],$folder_hash, true); - if($sync) - build_sync_packet($page_owner_uid,array('file' => array($sync))); + if($sync) + build_sync_packet($page_owner_uid,array('file' => array($sync))); + } } } @@ -181,17 +181,22 @@ class Photos extends \Zotlabs\Web\Controller { $r = q("SELECT id, resource_id FROM photo WHERE ( xchan = '%s' or uid = %d ) AND resource_id = '%s' LIMIT 1", dbesc($ob_hash), intval(local_channel()), - dbesc(\App::$argv[2]) + dbesc(argv(2)) ); if($r) { - attach_delete($page_owner_uid, $r[0]['resource_id'], 1 ); + attach_delete($page_owner_uid, $r[0]['resource_id'], true ); $sync = attach_export_data(\App::$data['channel'],$r[0]['resource_id'], true); if($sync) build_sync_packet($page_owner_uid,array('file' => array($sync))); } - + elseif(is_site_admin()) { + // If the admin deletes a photo, don't sync + attach_delete($page_owner_uid, argv(2), true); + } + + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $_SESSION['album_return']); } diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php index 206b8c3d1..baefe62ec 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -35,10 +35,12 @@ class Ping extends \Zotlabs\Web\Controller { $result['birthdays_today'] = 0; $result['all_events'] = 0; $result['all_events_today'] = 0; - $result['notice'] = array(); - $result['info'] = array(); + $result['notice'] = []; + $result['info'] = []; $result['pubs'] = 0; $result['files'] = 0; + $result['forums'] = 0; + $result['forums_sub'] = []; if(! $_SESSION['static_loadtime']) $_SESSION['static_loadtime'] = datetime_convert(); @@ -401,7 +403,7 @@ class Ping extends \Zotlabs\Web\Controller { 'notify_link' => z_root() . '/admin/accounts', 'name' => $rr['account_email'], 'url' => '', - 'photo' => get_default_profile_photo(48), + 'photo' => z_root() . '/' . get_default_profile_photo(48), 'when' => relative_date($rr['account_created']), 'hclass' => ('notify-unseen'), 'message' => t('requires approval') @@ -622,6 +624,58 @@ class Ping extends \Zotlabs\Web\Controller { if(! ($vnotify & VNOTIFY_BIRTHDAY)) $result['birthdays'] = 0; + + + if($vnotify & VNOTIFY_FORUMS) { + $forums = get_forum_channels(local_channel()); + + if(! $forums) { + $result['forums'] = 0; + } + else { + + $perms_sql = item_permissions_sql(local_channel()) . item_normal(); + $fcount = count($forums); + $forums['total'] = 0; + + for($x = 0; $x < $fcount; $x ++) { + $r = q("select sum(item_unseen) as unseen from item + where uid = %d and owner_xchan = '%s' and item_unseen = 1 $perms_sql ", + intval(local_channel()), + dbesc($forums[$x]['xchan_hash']) + ); + if($r[0]['unseen']) { + $forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&cid=' . $forums[$x]['abook_id']); + $forums[$x]['name'] = $forums[$x]['xchan_name']; + $forums[$x]['url'] = $forums[$x]['xchan_url']; + $forums[$x]['photo'] = $forums[$x]['xchan_photo_s']; + $forums[$x]['unseen'] = $r[0]['unseen']; + $forums[$x]['private_forum'] = (($forums[$x]['private_forum']) ? 'lock' : ''); + $forums[$x]['message'] = (($forums[$x]['private_forum']) ? t('Private forum') : t('Public forum')); + + $forums['total'] = $forums['total'] + $r[0]['unseen']; + + unset($forums[$x]['abook_id']); + unset($forums[$x]['xchan_hash']); + unset($forums[$x]['xchan_name']); + unset($forums[$x]['xchan_url']); + unset($forums[$x]['xchan_photo_s']); + + //if($forums[$x]['private_forum']) + // unset($forums[$x]['private_forum']); + + } + else { + unset($forums[$x]); + } + } + $result['forums'] = $forums['total']; + unset($forums['total']); + + $result['forums_sub'] = $forums; + } + } + $x = json_encode($result); $t8 = dba_timer(); diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 42c485f00..7b80a3978 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -66,8 +66,7 @@ class Pubstream extends \Zotlabs\Web\Controller { 'default_location' => $channel['channel_location'], 'nickname' => $channel['channel_address'], 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), - - 'acl' => populate_acl($channel_acl), + 'acl' => populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post'), 'permissions' => $channel_acl, 'bang' => '', 'visitor' => true, @@ -77,7 +76,8 @@ class Pubstream extends \Zotlabs\Web\Controller { 'editor_autocomplete' => true, 'bbco_autocomplete' => 'bbcode', 'bbcode' => true, - 'jotnets' => true + 'jotnets' => true, + 'reset' => t('Reset form') ); $o = '<div id="jot-popup">'; diff --git a/Zotlabs/Module/Register.php b/Zotlabs/Module/Register.php index 5356669e9..3dded19c7 100644 --- a/Zotlabs/Module/Register.php +++ b/Zotlabs/Module/Register.php @@ -187,8 +187,8 @@ class Register extends \Zotlabs\Web\Controller { $registration_is = ''; $other_sites = ''; - if(get_config('system','register_policy') == REGISTER_CLOSED) { - if(get_config('system','directory_mode') == DIRECTORY_MODE_STANDALONE) { + if(intval(get_config('system','register_policy')) === REGISTER_CLOSED) { + if(intval(get_config('system','directory_mode')) === DIRECTORY_MODE_STANDALONE) { notice( t('Registration on this hub is disabled.') . EOL); return; } @@ -197,10 +197,19 @@ class Register extends \Zotlabs\Web\Controller { return $mod->get(); } - if(get_config('system','register_policy') == REGISTER_APPROVE) { + if(intval(get_config('system','register_policy')) == REGISTER_APPROVE) { $registration_is = t('Registration on this hub is by approval only.'); $other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>'); } + + + $invitations = false; + + if(intval(get_config('system','invitation_only'))) { + $invitations = true; + $registration_is = t('Registration on this hub is by invitation only.'); + $other_sites = t('<a href="pubsites">Register at another affiliated hub.</a>'); + } $max_dailies = intval(get_config('system','max_daily_registrations')); if($max_dailies) { @@ -251,10 +260,10 @@ class Register extends \Zotlabs\Web\Controller { $password = array('password', t('Choose a password'), ''); $password2 = array('password2', t('Please re-enter your password'), ''); $invite_code = array('invite_code', t('Please enter your invitation code'), ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : "")); - $name = array('name', t('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"')); + $name = array('name', t('Your Name'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Real names are preferred.')); $nickhub = '@' . str_replace(array('http://','https://','/'), '', get_config('system','baseurl')); $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub)); - $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel role with your privacy requirements.') . ' <a href="help/member/member_guide#Account_Permission_Roles" target="_blank">' . t('Read more about roles') . '</a>',$perm_roles); + $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel permission role for your usage needs and privacy requirements.') . ' <a href="help/member/member_guide#Channel_Permission_Roles" target="_blank">' . t('Read more about channel permission roles') . '</a>',$perm_roles); $tos = array('tos', $label_tos, '', '', array(t('no'),t('yes'))); @@ -270,8 +279,7 @@ class Register extends \Zotlabs\Web\Controller { '$reg_is' => $registration_is, '$registertext' => bbcode(get_config('system','register_text')), '$other_sites' => $other_sites, - '$invitations' => get_config('system','invitation_only'), - '$invite_desc' => t('Membership on this site is by invitation only.'), + '$invitations' => $invitations, '$invite_code' => $invite_code, '$auto_create' => $auto_create, '$name' => $name, diff --git a/Zotlabs/Module/Regmod.php b/Zotlabs/Module/Regmod.php index 70635d707..6fe89ca90 100644 --- a/Zotlabs/Module/Regmod.php +++ b/Zotlabs/Module/Regmod.php @@ -13,8 +13,7 @@ class Regmod extends \Zotlabs\Web\Controller { if(! local_channel()) { info( t('Please login.') . EOL); - $o .= '<br /><br />' . login((\App::$config['system']['register_policy'] == REGISTER_CLOSED) ? 0 : 1); - return $o; + return login(); } if(! is_site_admin()) { diff --git a/Zotlabs/Module/Removeme.php b/Zotlabs/Module/Removeme.php index ca2080e83..451e280c3 100644 --- a/Zotlabs/Module/Removeme.php +++ b/Zotlabs/Module/Removeme.php @@ -38,7 +38,7 @@ class Removeme extends \Zotlabs\Web\Controller { } $global_remove = intval($_POST['global']); - + channel_remove(local_channel(),1 - $global_remove,true); } @@ -56,12 +56,12 @@ class Removeme extends \Zotlabs\Web\Controller { $tpl = get_markup_template('removeme.tpl'); $o .= replace_macros($tpl, array( '$basedir' => z_root(), - '$hash' => $hash, - '$title' => t('Remove This Channel'), - '$desc' => array(t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!')), - '$passwd' => t('Please enter your password for verification:'), - '$global' => array('global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), array(t('No'),t('Yes'))), - '$submit' => t('Remove Channel') + '$hash' => $hash, + '$title' => t('Remove This Channel'), + '$desc' => [ t('WARNING: '), t('This channel will be completely removed from the network. '), t('This action is permanent and can not be undone!') ], + '$passwd' => t('Please enter your password for verification:'), + '$global' => [ 'global', t('Remove this channel and all its clones from the network'), false, t('By default only the instance of the channel located on this hub will be removed from the network'), [ t('No'),t('Yes') ] ], + '$submit' => t('Remove Channel') )); return $o; 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/Module/Rpost.php b/Zotlabs/Module/Rpost.php index f0c4a06b9..86ee296ec 100644 --- a/Zotlabs/Module/Rpost.php +++ b/Zotlabs/Module/Rpost.php @@ -142,6 +142,7 @@ class Rpost extends \Zotlabs\Web\Controller { $o .= replace_macros(get_markup_template('edpost_head.tpl'), array( '$title' => t('Edit post'), + '$cancel' => '', '$editor' => $editor )); diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 3e928ec58..3a6e03588 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -21,6 +21,10 @@ class Channel { $role = ((x($_POST,'permissions_role')) ? notags(trim($_POST['permissions_role'])) : ''); $oldrole = get_pconfig(local_channel(),'system','permissions_role'); + // This mapping can be removed after 3.4 release + if($oldrole === 'social_party') { + $oldrole = 'social_federation'; + } if(($role != $oldrole) || ($role === 'custom')) { @@ -142,6 +146,7 @@ class Channel { $unkmail = (((x($_POST,'unkmail')) && (intval($_POST['unkmail']) == 1)) ? 1: 0); $cntunkmail = ((x($_POST,'cntunkmail')) ? intval($_POST['cntunkmail']) : 0); $suggestme = ((x($_POST,'suggestme')) ? intval($_POST['suggestme']) : 0); + $autoperms = ((x($_POST,'autoperms')) ? intval($_POST['autoperms']) : 0); $post_newfriend = (($_POST['post_newfriend'] == 1) ? 1: 0); $post_joingroup = (($_POST['post_joingroup'] == 1) ? 1: 0); @@ -210,6 +215,8 @@ class Channel { $vnotify += intval($_POST['vnotify13']); if(x($_POST,'vnotify14')) $vnotify += intval($_POST['vnotify14']); + if(x($_POST,'vnotify15')) + $vnotify += intval($_POST['vnotify15']); $always_show_in_notices = x($_POST,'always_show_in_notices') ? 1 : 0; @@ -248,6 +255,7 @@ class Channel { 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", dbesc($username), @@ -471,13 +479,25 @@ class Channel { $permissions_role = get_pconfig(local_channel(),'system','permissions_role'); if(! $permissions_role) $permissions_role = 'custom'; - + // compatibility mapping - can be removed after 3.4 release + if($permissions_role === 'social_party') + $permissions_role = 'social_federation'; + + if(in_array($permissions_role,['forum','repository'])) + $autoperms = replace_macros(get_markup_template('field_checkbox.tpl'), [ + '$field' => [ 'autoperms',t('Automatic membership approval'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no ]]); + else + $autoperms = '<input type="hidden" name="autoperms" value="' . intval(get_pconfig(local_channel(),'system','autoperms')) . '" />'; + $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'); if($vnotify === false) @@ -489,6 +509,7 @@ class Channel { $disable_discover_tab = intval(get_config('system','disable_discover_tab',1)) == 1; $site_firehose = intval(get_config('system','site_firehose',0)) == 1; + $o .= replace_macros($stpl,array( '$ptitle' => t('Channel Settings'), @@ -545,7 +566,7 @@ class Channel { '$unkmail' => $unkmail, '$cntunkmail' => array('cntunkmail', t('Maximum private messages per day from unknown people:'), intval($channel['channel_max_anon_mail']) ,t("Useful to reduce spamming")), - + '$autoperms' => $autoperms, '$h_not' => t('Notification Settings'), '$activity_options' => t('By default post a status message when:'), '$post_newfriend' => array('post_newfriend', t('accepting a friend request'), $post_newfriend, '', $yes_no), @@ -580,6 +601,7 @@ class Channel { '$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)), '$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()) ], '$always_show_in_notices' => array('always_show_in_notices', t('Show new wall posts, private messages and connections under Notices'), $always_show_in_notices, 1, '', $yes_no), diff --git a/Zotlabs/Module/Settings/Tokens.php b/Zotlabs/Module/Settings/Tokens.php index bf22ec7aa..619c8b5ba 100644 --- a/Zotlabs/Module/Settings/Tokens.php +++ b/Zotlabs/Module/Settings/Tokens.php @@ -161,8 +161,8 @@ class Tokens { '$me' => t('My Settings'), '$perms' => $perms, '$inherited' => t('inherited'), - '$notself' => 0, - '$self' => 1, + '$notself' => 1, + '$self' => 0, '$permlbl' => t('Individual Permissions'), '$permnote' => t('Some permissions may be inherited from your channel\'s <a href="settings"><strong>privacy settings</strong></a>, which have higher priority than individual settings. You can <strong>not</strong> change those settings here.'), '$submit' => t('Submit') @@ -170,4 +170,4 @@ class Tokens { return $o; } -}
\ No newline at end of file +} diff --git a/Zotlabs/Module/Siteinfo.php b/Zotlabs/Module/Siteinfo.php index 92ee78cc6..25276815d 100644 --- a/Zotlabs/Module/Siteinfo.php +++ b/Zotlabs/Module/Siteinfo.php @@ -12,6 +12,9 @@ class Siteinfo extends \Zotlabs\Web\Controller { } function get() { + + $federated = []; + call_hooks('federated_transports',$federated); $siteinfo = replace_macros(get_markup_template('siteinfo.tpl'), [ @@ -27,6 +30,9 @@ class Siteinfo extends \Zotlabs\Web\Controller { '$prj_name' => t('This site is powered by $Projectname'), '$prj_transport' => t('Federated and decentralised networking and identity services provided by Zot'), '$transport_link' => '<a href="https://zotlabs.com">https://zotlabs.com</a>', + + '$additional_text' => t('Additional federated transport protocols:'), + '$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'), diff --git a/Zotlabs/Module/Sources.php b/Zotlabs/Module/Sources.php index a180d9b6e..91e2efa60 100644 --- a/Zotlabs/Module/Sources.php +++ b/Zotlabs/Module/Sources.php @@ -12,12 +12,13 @@ class Sources extends \Zotlabs\Web\Controller { return ''; $source = intval($_REQUEST['source']); - $xchan = $_REQUEST['xchan']; + $xchan = escape_tags($_REQUEST['xchan']); $abook = intval($_REQUEST['abook']); - $words = $_REQUEST['words']; + $words = escape_tags($_REQUEST['words']); + $resend = intval($_REQUEST['resend']); $frequency = $_REQUEST['frequency']; - $name = $_REQUEST['name']; - $tags = $_REQUEST['tags']; + $name = escape_tags($_REQUEST['name']); + $tags = escape_tags($_REQUEST['tags']); $channel = \App::get_channel(); @@ -38,6 +39,8 @@ class Sources extends \Zotlabs\Web\Controller { return; } + set_abconfig(local_channel(),$xchan, 'system','rself',$resend); + if(! $source) { $r = q("insert into source ( src_channel_id, src_channel_xchan, src_xchan, src_patt, src_tag ) values ( %d, '%s', '%s', '%s', '%s' ) ", @@ -69,7 +72,7 @@ class Sources extends \Zotlabs\Web\Controller { } - function get() { + function get() { if(! local_channel()) { notice( t('Permission denied.') . EOL); return ''; @@ -110,7 +113,7 @@ class Sources extends \Zotlabs\Web\Controller { '$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'), '', ''), '$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') )); return $o; @@ -145,6 +148,8 @@ class Sources extends \Zotlabs\Web\Controller { '$xchan' => $r[0]['src_xchan'], '$abook' => $x[0]['abook_id'], '$tags' => array('tags', t('Add the following categories to posts imported from this source (comma separated)'),$r[0]['src_tag'],t('Optional')), + '$resend' => [ 'resend', t('Resend posts with this channel as author'), get_abconfig(local_channel(), $r[0]['xchan_hash'],'system','rself'), t('Copyrights may apply'), [ t('No'), t('Yes') ]], + '$name' => array( 'name', t('Channel Name'), $r[0]['xchan_name'], ''), '$submit' => t('Submit') )); diff --git a/Zotlabs/Module/Viewsrc.php b/Zotlabs/Module/Viewsrc.php index 54ab89e81..5900e385a 100644 --- a/Zotlabs/Module/Viewsrc.php +++ b/Zotlabs/Module/Viewsrc.php @@ -28,7 +28,7 @@ class Viewsrc extends \Zotlabs\Web\Controller { $item_normal = item_normal(); if(local_channel() && $item_id) { - $r = q("select id, item_flags, mimetype, item_obscured, body from item where uid in (%d , %d) and id = %d $item_normal limit 1", + $r = q("select id, item_flags, mimetype, item_obscured, body, llink, plink from item where uid in (%d , %d) and id = %d $item_normal limit 1", intval(local_channel()), intval($sys['channel_id']), intval($item_id) @@ -52,8 +52,11 @@ class Viewsrc extends \Zotlabs\Web\Controller { } if(is_ajax()) { - print '<div><i class="fa fa-pencil"> ' . t('Source of Item') . ' ' . $r[0]['id'] . '</i></div>'; - echo $o; + echo '<div class="p-1">'; + echo '<div>id: ' . $r[0]['id'] . ' | <a href="' . $r[0]['plink'] . '" target="_blank">plink</a> | <a href="' . $r[0]['llink'] . '" target="_blank">llink</a></div>'; + echo '<hr>'; + echo '<pre class="p-1">' . $o . '</pre>'; + echo '</div>'; killme(); } diff --git a/Zotlabs/Module/Well_known.php b/Zotlabs/Module/Well_known.php index 177de2323..442994b54 100644 --- a/Zotlabs/Module/Well_known.php +++ b/Zotlabs/Module/Well_known.php @@ -50,7 +50,15 @@ class Well_known extends \Zotlabs\Web\Controller { $module = new \Zotlabs\Module\Hostxrd(); $module->init(); break; - + + case 'oauth-authorization-server': + \App::$argc -= 1; + array_shift(\App::$argv); + \App::$argv[0] = 'oauthinfo'; + $module = new \Zotlabs\Module\Oauthinfo(); + $module->init(); + break; + case 'dnt-policy.txt': echo file_get_contents('doc/dnt-policy.txt'); killme(); diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php index 81d4beaed..88cb3e879 100644 --- a/Zotlabs/Module/Wfinger.php +++ b/Zotlabs/Module/Wfinger.php @@ -109,7 +109,8 @@ class Wfinger extends \Zotlabs\Web\Controller { $aliases = array( z_root() . (($pchan) ? '/pchan/' : '/channel/') . $r[0]['channel_address'], - z_root() . '/~' . $r[0]['channel_address'] + z_root() . '/~' . $r[0]['channel_address'], + z_root() . '/@' . $r[0]['channel_address'] ); if($h) { diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 7dc8eb1bc..322a3933c 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -95,7 +95,7 @@ class Wiki extends \Zotlabs\Web\Controller { $owner['channel_deny_gid']) ? 'lock' : 'unlock' ), - 'acl' => populate_acl($owner_acl), + 'acl' => populate_acl($owner_acl, false, \Zotlabs\Lib\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']), diff --git a/Zotlabs/Storage/BasicAuth.php b/Zotlabs/Storage/BasicAuth.php index d8af03703..a5c01fbb7 100644 --- a/Zotlabs/Storage/BasicAuth.php +++ b/Zotlabs/Storage/BasicAuth.php @@ -253,11 +253,11 @@ class BasicAuth extends DAV\Auth\Backend\AbstractBasic { * @return void */ public function log() { - logger('channel_name ' . $this->channel_name, LOGGER_DATA); - logger('channel_id ' . $this->channel_id, LOGGER_DATA); - logger('channel_hash ' . $this->channel_hash, LOGGER_DATA); - logger('observer ' . $this->observer, LOGGER_DATA); - logger('owner_id ' . $this->owner_id, LOGGER_DATA); - logger('owner_nick ' . $this->owner_nick, LOGGER_DATA); +// logger('channel_name ' . $this->channel_name, LOGGER_DATA); +// logger('channel_id ' . $this->channel_id, LOGGER_DATA); +// logger('channel_hash ' . $this->channel_hash, LOGGER_DATA); +// logger('observer ' . $this->observer, LOGGER_DATA); +// logger('owner_id ' . $this->owner_id, LOGGER_DATA); +// logger('owner_nick ' . $this->owner_nick, LOGGER_DATA); } } diff --git a/Zotlabs/Storage/Browser.php b/Zotlabs/Storage/Browser.php index 508c39d22..c2d70b854 100644 --- a/Zotlabs/Storage/Browser.php +++ b/Zotlabs/Storage/Browser.php @@ -12,7 +12,7 @@ use Sabre\DAV; * * @extends \\Sabre\\DAV\\Browser\\Plugin * - * @link http://github.com/redmatrix/hubzilla + * @link http://framagit.org/hubzilla/core/ * @license http://opensource.org/licenses/mit-license.php The MIT License (MIT) */ class Browser extends DAV\Browser\Plugin { @@ -241,7 +241,7 @@ class Browser extends DAV\Browser\Plugin { // put the array for this file together $ft['attachId'] = $this->findAttachIdByHash($attachHash); - $ft['fileStorageUrl'] = substr($fullPath, 0, strpos($fullPath, "cloud/")) . "filestorage/" . $this->auth->getCurrentUser(); + $ft['fileStorageUrl'] = substr($fullPath, 0, strpos($fullPath, "cloud/")) . "filestorage/" . $this->auth->owner_nick; $ft['icon'] = $icon; $ft['photo_icon'] = $photo_icon; $ft['attachIcon'] = (($size) ? $attachIcon : ''); @@ -276,6 +276,8 @@ class Browser extends DAV\Browser\Plugin { '$create' => t('Create'), '$upload' => t('Add Files'), '$is_owner' => $is_owner, + '$is_admin' => is_site_admin(), + '$admin_delete' => t('Admin Delete'), '$parentpath' => $parentpath, '$cpath' => bin2hex(\App::$query_string), '$tiles' => intval($_SESSION['cloud_tiles']), @@ -331,6 +333,7 @@ class Browser extends DAV\Browser\Plugin { $aclselect = null; $lockstate = ''; + $limit = 0; if($this->auth->owner_id) { $channel = channelx_by_n($this->auth->owner_id); @@ -341,10 +344,15 @@ class Browser extends DAV\Browser\Plugin { $aclselect = ((local_channel() == $this->auth->owner_id) ? populate_acl($channel_acl,false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')) : ''); } + + // Storage and quota for the account (all channels of the owner of this directory)! + $limit = engr_units_to_bytes(service_class_fetch($this->auth->owner_id, 'attach_upload_limit')); + } + + if((! $limit) && get_config('system','cloud_report_disksize')) { + $limit = engr_units_to_bytes(disk_free_space('store')); } - // Storage and quota for the account (all channels of the owner of this directory)! - $limit = engr_units_to_bytes(service_class_fetch($owner, 'attach_upload_limit')); $r = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d", intval($this->auth->channel_account_id) ); diff --git a/Zotlabs/Storage/Directory.php b/Zotlabs/Storage/Directory.php index 7068ee15a..642af6300 100644 --- a/Zotlabs/Storage/Directory.php +++ b/Zotlabs/Storage/Directory.php @@ -571,39 +571,6 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo return datetime_convert('UTC', 'UTC', $r[0]['edited'], 'U'); } - /** - * @brief Return quota usage. - * - * @fixme Should guests relly see the used/free values from filesystem of the - * complete store directory? - * - * @return array with used and free values in bytes. - */ - public function getQuotaInfo() { - // values from the filesystem of the complete <i>store/</i> directory - $limit = disk_total_space('store'); - $free = disk_free_space('store'); - - if ($this->auth->owner_id) { - $c = q("select * from channel where channel_id = %d and channel_removed = 0 limit 1", - intval($this->auth->owner_id) - ); - - $ulimit = engr_units_to_bytes(service_class_fetch($c[0]['channel_id'], 'attach_upload_limit')); - $limit = (($ulimit) ? $ulimit : $limit); - - $x = q("select sum(filesize) as total from attach where aid = %d", - intval($c[0]['channel_account_id']) - ); - $free = (($x) ? $limit - $x[0]['total'] : 0); - } - - return array( - $limit - $free, - $free - ); - } - /** * @brief Array with all Directory and File DAV\\Node items for the given path. @@ -719,6 +686,8 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo ); foreach ($r as $rr) { + if(\App::$module === 'cloud' && (strpos($rr['filename'],'.') === 0) && (! get_pconfig($channel_id,'system','show_dot_files')) ) + continue; // @FIXME I don't think we use revisions currently in attach structures. // In case we see any in the wild provide a unique filename. This @@ -753,14 +722,13 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo function ChannelList(&$auth) { $ret = array(); - $r = q("SELECT channel_id, channel_address FROM channel WHERE channel_removed = 0 - AND channel_system = 0 AND (channel_pageflags & %d) = 0", + $r = q("SELECT channel_id, channel_address, profile.publish FROM channel left join profile on profile.uid = channel.channel_id WHERE channel_removed = 0 AND channel_system = 0 AND (channel_pageflags & %d) = 0", intval(PAGE_HIDDEN) ); if ($r) { foreach ($r as $rr) { - if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage')) { + if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage') && $rr['publish']) { logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA); // @todo can't we drop '/cloud'? It gets stripped off anyway in RedDirectory $ret[] = new Directory('/cloud/' . $rr['channel_address'], $auth); @@ -893,4 +861,48 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo return false; } + public function getQuotaInfo() { + + /** + * Returns the quota information + * + * This method MUST return an array with 2 values, the first being the total used space, + * the second the available space (in bytes) + */ + + $used = 0; + $limit = 0; + $free = 0; + + if ($this->auth->owner_id) { + $channel = channelx_by_n($this->auth->owner_id); + if($channel) { + $r = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d", + intval($channel['channel_account_id']) + ); + $used = (($r) ? (float) $r[0]['total'] : 0); + $limit = (float) service_class_fetch($this->auth->owner_id, 'attach_upload_limit'); + if($limit) { + // Don't let the result go negative + $free = (($limit > $used) ? $limit - $used : 0); + } + } + } + + if(! $limit) { + $free = disk_free_space('store'); + $used = disk_total_space('store') - $free; + } + + // prevent integer overflow on 32-bit systems + + if($used > (float) PHP_INT_MAX) + $used = PHP_INT_MAX; + if($free > (float) PHP_INT_MAX) + $free = PHP_INT_MAX; + + return [ (int) $used, (int) $free ]; + + } + } diff --git a/Zotlabs/Thumbs/Pdf.php b/Zotlabs/Thumbs/Pdf.php index 98bcf11b5..11714ad53 100644 --- a/Zotlabs/Thumbs/Pdf.php +++ b/Zotlabs/Thumbs/Pdf.php @@ -27,7 +27,7 @@ class Pdf { $imagick_path = get_config('system','imagick_convert_path'); if($imagick_path && @file_exists($imagick_path)) { - $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmpfile . '[0]') . ' -thumbnail ' . $width . 'x' . $height . ' ' . escapeshellarg(PROJECT_BASE . '/' . $outfile); + $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmpfile . '[0]') . ' -resize ' . $width . 'x' . $height . ' ' . escapeshellarg(PROJECT_BASE . '/' . $outfile); // logger('imagick thumbnail command: ' . $cmd); for($x = 0; $x < 4; $x ++) { exec($cmd); diff --git a/Zotlabs/Thumbs/Video.php b/Zotlabs/Thumbs/Video.php index ff4d10a36..15d3ace12 100644 --- a/Zotlabs/Thumbs/Video.php +++ b/Zotlabs/Thumbs/Video.php @@ -46,7 +46,7 @@ class Video { $imagick_path = get_config('system','imagick_convert_path'); if($imagick_path && @file_exists($imagick_path)) { - $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmpfile . '[0]') . ' -thumbnail ' . $width . 'x' . $height . ' ' . escapeshellarg(PROJECT_BASE . '/' . $outfile); + $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmpfile . '[0]') . ' -resize ' . $width . 'x' . $height . ' ' . escapeshellarg(PROJECT_BASE . '/' . $outfile); // logger('imagick thumbnail command: ' . $cmd); /** @scrutinizer ignore-unhandled */ diff --git a/Zotlabs/Web/CheckJS.php b/Zotlabs/Web/CheckJS.php index 8179ceb15..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 = urlencode(\App::$query_string); + $page = bin2hex(\App::$query_string); + if(! $this->jsdisabled) { if($test) { $this->jsdisabled = 1; if(array_key_exists('jsdisabled',$_COOKIE)) diff --git a/Zotlabs/Widget/Activity_filter.php b/Zotlabs/Widget/Activity_filter.php new file mode 100644 index 000000000..fadf39144 --- /dev/null +++ b/Zotlabs/Widget/Activity_filter.php @@ -0,0 +1,204 @@ +<?php + +namespace Zotlabs\Widget; + +class Activity_filter { + + function widget($arr) { + + if(! local_channel()) + return ''; + + $cmd = \App::$cmd; + $filter_active = false; + + $tabs = []; + + if(feature_enabled(local_channel(),'personal_tab')) { + if(x($_GET,'conv')) { + $conv_active = (($_GET['conv'] == 1) ? 'active' : ''); + $filter_active = 'personal'; + } + + $tabs[] = [ + 'label' => t('Personal Posts'), + 'icon' => 'user-circle', + 'url' => z_root() . '/' . $cmd . '/?f=&conv=1', + 'sel' => $conv_active, + 'title' => t('Show posts that mention or involve me') + ]; + } + + if(feature_enabled(local_channel(),'star_posts')) { + if(x($_GET,'star')) { + $starred_active = (($_GET['star'] == 1) ? 'active' : ''); + $filter_active = 'star'; + } + + $tabs[] = [ + 'label' => t('Starred Posts'), + 'icon' => 'star', + 'url'=>z_root() . '/' . $cmd . '/?f=&star=1', + 'sel'=>$starred_active, + 'title' => t('Show posts that I have starred') + ]; + } + + if(feature_enabled(local_channel(),'groups')) { + $groups = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC", + intval(local_channel()) + ); + + if($groups) { + foreach($groups as $g) { + if(x($_GET,'gid')) { + $group_active = (($_GET['gid'] == $g['id']) ? 'active' : ''); + $filter_active = 'group'; + } + $gsub[] = [ + 'label' => $g['gname'], + 'icon' => '', + 'url' => z_root() . '/' . $cmd . '/?f=&gid=' . $g['id'], + 'sel' => $group_active, + 'title' => sprintf(t('Show posts related to the %s privacy group'), $g['gname']) + ]; + } + $tabs[] = [ + 'id' => 'privacy_groups', + 'label' => t('Privacy Groups'), + 'icon' => 'users', + 'url' => '#', + 'sel' => (($filter_active == 'group') ? true : false), + 'title' => t('Show my privacy groups'), + 'sub' => $gsub + + ]; + } + } + + if(feature_enabled(local_channel(),'forums_tab')) { + $forums = get_forum_channels(local_channel()); + + if($forums) { + foreach($forums as $f) { + if(x($_GET,'pf') && x($_GET,'cid')) { + $forum_active = ((x($_GET,'pf') && $_GET['cid'] == $f['abook_id']) ? 'active' : ''); + $filter_active = 'forums'; + } + $fsub[] = [ + 'label' => $f['xchan_name'], + 'img' => $f['xchan_photo_s'], + 'url' => (($f['private_forum']) ? $f['xchan_url'] : z_root() . '/' . $cmd . '/?f=&pf=1&cid=' . $f['abook_id']), + 'sel' => $forum_active, + 'title' => t('Show posts to this forum'), + 'lock' => (($f['private_forum']) ? 'lock' : '') + ]; + } + + $tabs[] = [ + 'id' => 'forums', + 'label' => t('Forums'), + 'icon' => 'comments-o', + 'url' => '#', + 'sel' => (($filter_active == 'forums') ? true : false), + 'title' => t('Show forums'), + 'sub' => $fsub + + ]; + } + } + + if(feature_enabled(local_channel(),'filing')) { + $terms = q("select distinct term from term where uid = %d and ttype = %d order by term asc", + intval(local_channel()), + intval(TERM_FILE) + ); + + if($terms) { + foreach($terms as $t) { + if(x($_GET,'file')) { + $file_active = (($_GET['file'] == $t['term']) ? 'active' : ''); + $filter_active = 'file'; + } + $tsub[] = [ + 'label' => $t['term'], + 'icon' => '', + 'url' => z_root() . '/' . $cmd . '/?f=&file=' . $t['term'], + 'sel' => $file_active, + 'title' => sprintf(t('Show posts that I have filed to %s'), $t['term']), + ]; + } + + $tabs[] = [ + 'id' => 'saved_folders', + 'label' => t('Saved Folders'), + 'icon' => 'folder', + 'url' => '#', + 'sel' => (($filter_active == 'file') ? true : false), + 'title' => t('Show filed post categories'), + 'sub' => $tsub + + ]; + } + } + + if(x($_GET,'search')) { + $filter_active = 'search'; + $tabs[] = [ + 'label' => t('Search'), + 'icon' => 'search', + 'url' => z_root() . '/' . $cmd . '/?f=&search=' . $_GET['search'], + 'sel' => 'active disabled', + 'title' => t('Panel search') + ]; + } + + $name = []; + if(feature_enabled(local_channel(),'name_tab')) { + if(x($_GET,'cid') && ! x($_GET,'pf')) { + $filter_active = 'name'; + } + $name = [ + 'label' => x($_GET,'name') ? $_GET['name'] : t('Filter by name'), + 'icon' => 'filter', + 'url'=> z_root() . '/' . $cmd . '/', + 'sel'=> $filter_active == 'name' ? 'is-valid' : '', + 'title' => '' + ]; + } + + $reset = []; + if($filter_active) { + $reset = [ + 'label' => '', + 'icon' => 'remove', + 'url'=> z_root() . '/' . $cmd, + 'sel'=> '', + 'title' => t('Remove active filter') + ]; + } + + $arr = ['tabs' => $tabs]; + + call_hooks('network_tabs', $arr); + + $o = ''; + + if($arr['tabs']) { + $content = replace_macros(get_markup_template('common_pills.tpl'), [ + '$pills' => $arr['tabs'] + ]); + + $o .= replace_macros(get_markup_template('activity_filter_widget.tpl'), [ + '$title' => t('Activity Filters'), + '$reset' => $reset, + '$content' => $content, + '$name' => $name + ]); + } + + return $o; + + } + +} diff --git a/Zotlabs/Widget/Activity_order.php b/Zotlabs/Widget/Activity_order.php new file mode 100644 index 000000000..0e660afc3 --- /dev/null +++ b/Zotlabs/Widget/Activity_order.php @@ -0,0 +1,128 @@ +<?php + +namespace Zotlabs\Widget; + +class Activity_order { + + function widget($arr) { + + if(! local_channel()) + return ''; + + if(! feature_enabled(local_channel(),'order_tab')) { + set_pconfig(local_channel(), 'mod_network', 'order', 0); + return ''; + } + + $commentord_active = ''; + $postord_active = ''; + $unthreaded_active = ''; + + if(x($_GET, 'order')) { + switch($_GET['order']){ + case 'post': + $postord_active = 'active'; + set_pconfig(local_channel(), 'mod_network', 'order', 1); + break; + case 'comment': + $commentord_active = 'active'; + set_pconfig(local_channel(), 'mod_network', 'order', 0); + break; + case 'unthreaded': + $unthreaded_active = 'active'; + set_pconfig(local_channel(), 'mod_network', 'order', 2); + break; + default: + $commentord_active = 'active'; + } + } + else { + $order = get_pconfig(local_channel(), 'mod_network', 'order', 0); + switch($order) { + case 0: + $commentord_active = 'active'; + break; + case 1: + $postord_active = 'active'; + break; + case 2: + $unthreaded_active = 'active'; + break; + default: + $commentord_active = 'active'; + } + } + + // override order for search, filer and cid results + if(x($_GET,'search') || x($_GET,'file') || (! x($_GET,'pf') && x($_GET,'cid'))) { + $unthreaded_active = 'active'; + $commentord_active = $postord_active = 'disabled'; + } + + $cmd = \App::$cmd; + + $filter = ''; + + if(x($_GET,'cid')) + $filter .= '&cid=' . $_GET['cid']; + + if(x($_GET,'gid')) + $filter .= '&gid=' . $_GET['gid']; + + if(x($_GET,'star')) + $filter .= '&star=' . $_GET['star']; + + if(x($_GET,'conv')) + $filter .= '&conv=' . $_GET['conv']; + + if(x($_GET,'file')) + $filter .= '&file=' . $_GET['file']; + + + // tabs + $tabs = []; + + $tabs[] = [ + 'label' => t('Commented Date'), + 'icon' => '', + 'url'=>z_root() . '/' . $cmd . '?f=&order=comment' . $filter, + 'sel'=> $commentord_active, + 'title' => t('Order by last commented date'), + ]; + $tabs[] = [ + 'label' => t('Posted Date'), + 'icon' => '', + 'url'=>z_root() . '/' . $cmd . '?f=&order=post' . $filter, + 'sel'=> $postord_active, + 'title' => t('Order by last posted date'), + ]; + $tabs[] = array( + 'label' => t('Date Unthreaded'), + 'icon' => '', + 'url' => z_root() . '/' . $cmd . '?f=&order=unthreaded' . $filter, + 'sel' => $unthreaded_active, + 'title' => t('Order unthreaded by date'), + ); + + $arr = ['tabs' => $tabs]; + + call_hooks('network_tabs', $arr); + + $o = ''; + + if($arr['tabs']) { + $content = replace_macros(get_markup_template('common_pills.tpl'), [ + '$pills' => $arr['tabs'], + ]); + + $o = replace_macros(get_markup_template('common_widget.tpl'), [ + '$title' => t('Activity Order'), + '$content' => $content, + ]); + } + + return $o; + + } + +} diff --git a/Zotlabs/Widget/Admin.php b/Zotlabs/Widget/Admin.php index a761eebe3..f349377a0 100644 --- a/Zotlabs/Widget/Admin.php +++ b/Zotlabs/Widget/Admin.php @@ -24,7 +24,7 @@ class Admin { 'channels' => array(z_root() . '/admin/channels/', t('Channels'), 'channels'), 'security' => array(z_root() . '/admin/security/', t('Security'), 'security'), 'features' => array(z_root() . '/admin/features/', t('Features'), 'features'), - 'plugins' => array(z_root() . '/admin/plugins/', t('Plugins'), 'plugins'), + 'addons' => array(z_root() . '/admin/addons/', t('Addons'), 'addons'), 'themes' => array(z_root() . '/admin/themes/', t('Themes'), 'themes'), 'queue' => array(z_root() . '/admin/queue', t('Inspect queue'), 'queue'), 'profs' => array(z_root() . '/admin/profs', t('Profile Fields'), 'profs'), @@ -39,7 +39,7 @@ class Admin { if($r) { foreach ($r as $h){ $plugin = $h['aname']; - $plugins[] = array(z_root() . '/admin/plugins/' . $plugin, $plugin, 'plugin'); + $plugins[] = array(z_root() . '/admin/addons/' . $plugin, $plugin, 'plugin'); // temp plugins with admin \App::$plugins_admin[] = $plugin; } @@ -53,7 +53,7 @@ class Admin { $o .= replace_macros(get_markup_template('admin_aside.tpl'), array( '$admin' => $aside, '$admtxt' => t('Admin'), - '$plugadmtxt' => t('Plugin Features'), + '$plugadmtxt' => t('Addon Features'), '$plugins' => $plugins, '$logtxt' => t('Logs'), '$logs' => $logs, diff --git a/Zotlabs/Widget/Appcategories.php b/Zotlabs/Widget/Appcategories.php index 8ff14230f..aebd144d0 100644 --- a/Zotlabs/Widget/Appcategories.php +++ b/Zotlabs/Widget/Appcategories.php @@ -17,6 +17,9 @@ class Appcategories { // Leaving this line which negates the effect of the two invalid lines prior $srchurl = z_root() . '/apps'; + if(argc() > 1 && argv(1) === 'available') + $srchurl .= '/available'; + $terms = array(); diff --git a/Zotlabs/Widget/Appstore.php b/Zotlabs/Widget/Appstore.php new file mode 100644 index 000000000..237707733 --- /dev/null +++ b/Zotlabs/Widget/Appstore.php @@ -0,0 +1,18 @@ +<?php + +namespace Zotlabs\Widget; + + +class Appstore { + + function widget($arr) { + $store = ((argc() > 1 && argv(1) === 'available') ? 1 : 0); + 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 ] + ] + ]); + } +}
\ No newline at end of file diff --git a/Zotlabs/Widget/Collections.php b/Zotlabs/Widget/Collections.php index d2b29679a..bc9c812c6 100644 --- a/Zotlabs/Widget/Collections.php +++ b/Zotlabs/Widget/Collections.php @@ -8,6 +8,9 @@ class Collections { function widget($args) { + if(argc() < 2) + return; + $mode = ((array_key_exists('mode',$args)) ? $args['mode'] : 'conversation'); switch($mode) { case 'conversation': diff --git a/Zotlabs/Widget/Notifications.php b/Zotlabs/Widget/Notifications.php index fc78a2a39..a4cf4e706 100644 --- a/Zotlabs/Widget/Notifications.php +++ b/Zotlabs/Widget/Notifications.php @@ -111,6 +111,17 @@ class Notifications { 'label' => t('Mark all notices seen') ] ]; + + $notifications[] = [ + 'type' => 'forums', + 'icon' => 'comments-o', + 'severity' => 'secondary', + 'label' => t('Forums'), + 'title' => t('Forums'), + 'filter' => [ + 'name_label' => t('Filter by name') + ] + ]; } if(local_channel() && is_site_admin()) { diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index 9574becc3..f35d6f147 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -105,7 +105,7 @@ class Settings_menu { if(feature_enabled(local_channel(),'permcats')) { $tabs[] = array( - 'label' => t('Permission Groups'), + 'label' => t('Permission Categories'), 'url' => z_root() . '/settings/permcats', 'selected' => ((argv(1) === 'permcats') ? 'active' : ''), ); |