diff options
Diffstat (limited to 'Zotlabs')
50 files changed, 1750 insertions, 279 deletions
diff --git a/Zotlabs/Access/Permissions.php b/Zotlabs/Access/Permissions.php index 74286934f..62c4af0ff 100644 --- a/Zotlabs/Access/Permissions.php +++ b/Zotlabs/Access/Permissions.php @@ -201,6 +201,7 @@ class Permissions { * * \e array \b perms Permission array * * \e int \b automatic 0 or 1 */ + static public function connect_perms($channel_id) { $my_perms = []; diff --git a/Zotlabs/Daemon/Importdoc.php b/Zotlabs/Daemon/Importdoc.php index 3109a5d86..0ca589e4a 100755 --- a/Zotlabs/Daemon/Importdoc.php +++ b/Zotlabs/Daemon/Importdoc.php @@ -21,12 +21,18 @@ class Importdoc { $files = glob("$d/$f"); if($files) { foreach($files as $fi) { - if($fi === 'doc/html') + if($fi === 'doc/html') { continue; - if(is_dir($fi)) + } + if(is_dir($fi)) { self::update_docs_dir("$fi/*"); - else - store_doc_file($fi); + } + else { + // don't update media content + if(strpos(z_mime_content_type($fi),'text') === 0) { + store_doc_file($fi); + } + } } } } diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 16246b081..20dd96ddd 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -64,8 +64,6 @@ require_once('include/bbcode.php'); * purge_all channel_id * expire channel_id * relay item_id (item was relayed to owner, we will deliver it as owner) - * single_activity item_id (deliver to a singleton network from the appropriate clone) - * single_mail mail_id (deliver to a singleton network from the appropriate clone) * location channel_id * request channel_id xchan_hash message_id * rating xlink_id @@ -105,7 +103,7 @@ class Notifier { $normal_mode = true; $packet_type = 'undefined'; - if($cmd === 'mail' || $cmd === 'single_mail') { + if($cmd === 'mail') { $normal_mode = false; $mail = true; $private = true; @@ -392,7 +390,6 @@ class Notifier { return; } } - } $walltowall = (($top_level_post && $channel['xchan_hash'] === $target_item['author_xchan']) ? true : false); @@ -409,7 +406,7 @@ class Notifier { if(! $recipients) return; -// logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG); + // logger('notifier: recipients: ' . print_r($recipients,true), LOGGER_NORMAL, LOG_DEBUG); $env_recips = (($private) ? array() : null); @@ -422,40 +419,39 @@ class Notifier { foreach($details as $d) { $recip_list[] = $d['xchan_addr'] . ' (' . $d['xchan_hash'] . ')'; - if($private) - $env_recips[] = array('guid' => $d['xchan_guid'],'guid_sig' => $d['xchan_guid_sig'],'hash' => $d['xchan_hash']); - - if($d['xchan_network'] === 'mail' && $normal_mode) { - $delivery_options = get_xconfig($d['xchan_hash'],'system','delivery_mode'); - if(! $delivery_options) - format_and_send_email($channel,$d,$target_item); + if($private) { + $env_recips[] = [ + 'guid' => $d['xchan_guid'], + 'guid_sig' => $d['xchan_guid_sig'], + 'hash' => $d['xchan_hash'] + ]; } } } - $narr = array( - 'channel' => $channel, - 'upstream' => $upstream, - 'env_recips' => $env_recips, - 'packet_recips' => $packet_recips, - 'recipients' => $recipients, - 'item' => $item, - 'target_item' => $target_item, + $narr = [ + 'channel' => $channel, + 'upstream' => $upstream, + 'env_recips' => $env_recips, + 'packet_recips' => $packet_recips, + 'recipients' => $recipients, + 'item' => $item, + 'target_item' => $target_item, 'top_level_post' => $top_level_post, - 'private' => $private, + 'private' => $private, 'relay_to_owner' => $relay_to_owner, - 'uplink' => $uplink, - 'cmd' => $cmd, - 'mail' => $mail, - 'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false), - 'location' => $location, - 'request' => $request, - 'normal_mode' => $normal_mode, - 'packet_type' => $packet_type, - 'walltowall' => $walltowall, - 'queued' => array() - ); + 'uplink' => $uplink, + 'cmd' => $cmd, + 'mail' => $mail, + 'single' => false, + 'location' => $location, + 'request' => $request, + 'normal_mode' => $normal_mode, + 'packet_type' => $packet_type, + 'walltowall' => $walltowall, + 'queued' => [] + ]; call_hooks('notifier_process', $narr); if($narr['queued']) { @@ -492,8 +488,6 @@ class Notifier { $hubs = $r; - - /** * Reduce the hubs to those that are unique. For zot hubs, we need to verify uniqueness by the sitekey, * since it may have been a re-install which has not yet been detected and pruned. @@ -524,49 +518,47 @@ class Notifier { if($hub['hubloc_network'] == 'zot') { if(! in_array($hub['hubloc_sitekey'],$keys)) { $hublist[] = $hub['hubloc_host']; - $dhubs[] = $hub; - $keys[] = $hub['hubloc_sitekey']; + $dhubs[] = $hub; + $keys[] = $hub['hubloc_sitekey']; } } else { if(! in_array($hub['hubloc_url'],$urls)) { $hublist[] = $hub['hubloc_host']; - $dhubs[] = $hub; - $urls[] = $hub['hubloc_url']; + $dhubs[] = $hub; + $urls[] = $hub['hubloc_url']; } } } logger('notifier: will notify/deliver to these hubs: ' . print_r($hublist,true), LOGGER_DEBUG, LOG_DEBUG); - foreach($dhubs as $hub) { if($hub['hubloc_network'] !== 'zot') { - - $narr = array( - 'channel' => $channel, - 'upstream' => $upstream, - 'env_recips' => $env_recips, - 'packet_recips' => $packet_recips, - 'recipients' => $recipients, - 'item' => $item, - 'target_item' => $target_item, - 'hub' => $hub, + $narr = [ + 'channel' => $channel, + 'upstream' => $upstream, + 'env_recips' => $env_recips, + 'packet_recips' => $packet_recips, + 'recipients' => $recipients, + 'item' => $item, + 'target_item' => $target_item, + 'hub' => $hub, 'top_level_post' => $top_level_post, - 'private' => $private, + 'private' => $private, 'relay_to_owner' => $relay_to_owner, - 'uplink' => $uplink, - 'cmd' => $cmd, - 'mail' => $mail, - 'single' => (($cmd === 'single_mail' || $cmd === 'single_activity') ? true : false), - 'location' => $location, - 'request' => $request, - 'normal_mode' => $normal_mode, - 'packet_type' => $packet_type, - 'walltowall' => $walltowall, - 'queued' => array() - ); + 'uplink' => $uplink, + 'cmd' => $cmd, + 'mail' => $mail, + 'single' => false, + 'location' => $location, + 'request' => $request, + 'normal_mode' => $normal_mode, + 'packet_type' => $packet_type, + 'walltowall' => $walltowall, + 'queued' => [] + ]; call_hooks('notifier_hub',$narr); @@ -578,21 +570,6 @@ class Notifier { } - // singleton deliveries by definition 'not got zot'. - // Single deliveries are other federated networks (plugins) and we're essentially - // delivering only to those that have this site url in their abook_instance - // and only from within a sync operation. This means if you post from a clone, - // and a connection is connected to one of your other clones; assuming that hub - // is running it will receive a sync packet. On receipt of this sync packet it - // will invoke a delivery to those connections which are connected to just that - // hub instance. - - if($cmd === 'single_mail' || $cmd === 'single_activity') { - continue; - } - - // default: zot protocol - $hash = random_string(); $packet = null; @@ -618,14 +595,16 @@ class Notifier { else { $env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : ''); $packet = zot_build_packet($channel,'notify',$env,(($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash); - queue_insert(array( - 'hash' => $hash, - 'account_id' => $target_item['aid'], - 'channel_id' => $target_item['uid'], - 'posturl' => $hub['hubloc_callback'], - 'notify' => $packet, - 'msg' => json_encode($encoded_item) - )); + queue_insert( + [ + 'hash' => $hash, + 'account_id' => $target_item['aid'], + 'channel_id' => $target_item['uid'], + 'posturl' => $hub['hubloc_callback'], + 'notify' => $packet, + 'msg' => json_encode($encoded_item) + ] + ); // only create delivery reports for normal undeleted items if(is_array($target_item) && array_key_exists('postopts',$target_item) && (! $target_item['item_deleted']) && (! get_config('system','disable_dreport'))) { @@ -646,9 +625,9 @@ class Notifier { if($normal_mode) { $x = q("select * from hook where hook = 'notifier_normal'"); - if($x) - Master::Summon(array('Deliver_hooks',$target_item['id'])); - + if($x) { + Master::Summon( [ 'Deliver_hooks', $target_item['id'] ] ); + } } if($deliveries) diff --git a/Zotlabs/Extend/Hook.php b/Zotlabs/Extend/Hook.php index fef3ebe9b..c6f9ea850 100644 --- a/Zotlabs/Extend/Hook.php +++ b/Zotlabs/Extend/Hook.php @@ -40,6 +40,15 @@ class Hook { return $r; } + static public function register_array($file,$arr) { + if($arr) { + foreach($arr as $k => $v) { + self::register($k,$file,$v); + } + } + } + + static public function unregister($hook,$file,$function,$version = 1,$priority = 0) { if(is_array($function)) { $function = serialize($function); diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index ed18ff3cb..68587df49 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -209,6 +209,7 @@ class Apps { static public function translate_system_apps(&$arr) { $apps = array( + 'Apps' => t('Apps'), 'Site Admin' => t('Site Admin'), 'Report Bug' => t('Report Bug'), 'View Bookmarks' => t('View Bookmarks'), @@ -664,11 +665,6 @@ class Apps { } - - - - - static public function app_decode($s) { $x = base64_decode(str_replace(array('<br />',"\r","\n",' '),array('','','',''),$s)); return json_decode($x,true); diff --git a/Zotlabs/Lib/Cache.php b/Zotlabs/Lib/Cache.php index f211269be..cea075659 100644 --- a/Zotlabs/Lib/Cache.php +++ b/Zotlabs/Lib/Cache.php @@ -9,10 +9,10 @@ namespace Zotlabs\Lib; class Cache { public static function get($key) { - $key = substr($key,0,254); + $hash = hash('whirlpool',$key); $r = q("SELECT v FROM cache WHERE k = '%s' limit 1", - dbesc($key) + dbesc($hash) ); if ($r) @@ -22,20 +22,20 @@ class Cache { public static function set($key,$value) { - $key = substr($key,0,254); + $hash = hash('whirlpool',$key); $r = q("SELECT * FROM cache WHERE k = '%s' limit 1", - dbesc($key) + dbesc($hash) ); if($r) { q("UPDATE cache SET v = '%s', updated = '%s' WHERE k = '%s'", dbesc($value), dbesc(datetime_convert()), - dbesc($key)); + dbesc($hash)); } else { q("INSERT INTO cache ( k, v, updated) VALUES ('%s','%s','%s')", - dbesc($key), + dbesc($hash), dbesc($value), dbesc(datetime_convert())); } diff --git a/Zotlabs/Lib/Config.php b/Zotlabs/Lib/Config.php index 5625a3f79..6e042feba 100644 --- a/Zotlabs/Lib/Config.php +++ b/Zotlabs/Lib/Config.php @@ -53,7 +53,7 @@ class Config { $dbvalue = ((is_array($value)) ? serialize($value) : $value); $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue); - if(get_config($family, $key) === false || (! self::get_from_storage($family, $key))) { + if(self::Get($family, $key) === false || (! self::get_from_storage($family, $key))) { $ret = q("INSERT INTO config ( cat, k, v ) VALUES ( '%s', '%s', '%s' ) ", dbesc($family), dbesc($key), diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php index 90662ce84..9f3347d19 100644 --- a/Zotlabs/Lib/Enotify.php +++ b/Zotlabs/Lib/Enotify.php @@ -170,7 +170,7 @@ class Enotify { xchan_query($p); - $moderated = (($p[0]['item_blocked'] = ITEM_MODERATED) ? true : false); + $moderated = (($p[0]['item_blocked'] == ITEM_MODERATED) ? true : false); $item_post_type = item_post_type($p[0]); // $private = $p[0]['item_private']; diff --git a/Zotlabs/Lib/PConfig.php b/Zotlabs/Lib/PConfig.php index d70697fbc..25478e764 100644 --- a/Zotlabs/Lib/PConfig.php +++ b/Zotlabs/Lib/PConfig.php @@ -119,7 +119,7 @@ class PConfig { $dbvalue = ((is_array($value)) ? serialize($value) : $value); $dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue); - if(get_pconfig($uid, $family, $key) === false) { + if(self::Get($uid, $family, $key) === false) { if(! array_key_exists($uid, \App::$config)) \App::$config[$uid] = array(); if(! array_key_exists($family, \App::$config[$uid])) diff --git a/Zotlabs/Lib/System.php b/Zotlabs/Lib/System.php index 306c90f4a..3d5b18506 100644 --- a/Zotlabs/Lib/System.php +++ b/Zotlabs/Lib/System.php @@ -54,12 +54,8 @@ class System { return 'https://github.com/redmatrix/hubzilla'; } - - static public function get_server_role() { - if(is_array(\App::$config) && is_array(\App::$config['system']) && \App::$config['system']['server_role']) - return \App::$config['system']['server_role']; - return 'standard'; + return 'pro'; } static public function get_std_version() { @@ -72,11 +68,8 @@ class System { if(get_directory_realm() != DIRECTORY_REALM) return true; - - foreach(['hubzilla','zap'] as $t) { - if(stristr($p,$t)) - return true; - } + if(in_array(strtolower($p),['hubzilla','zap','red'])) + return true; return false; } } diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 917397686..72d8af4dd 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -251,8 +251,6 @@ class ThreadItem { ); } - $server_role = get_config('system','server_role'); - $has_bookmarks = false; if(is_array($item['term'])) { foreach($item['term'] as $t) { diff --git a/Zotlabs/Module/Admin.php b/Zotlabs/Module/Admin.php index 536d85dde..f2918dffc 100644 --- a/Zotlabs/Module/Admin.php +++ b/Zotlabs/Module/Admin.php @@ -91,10 +91,10 @@ class Admin extends \Zotlabs\Web\Controller { intval(ACCOUNT_BLOCKED) ); if ($r) { - $accounts['total'] = array('label' => t('# Accounts'), 'val' => $r[0]['total']); - $accounts['blocked'] = array('label' => t('# blocked accounts'), 'val' => $r[0]['blocked']); - $accounts['expired'] = array('label' => t('# expired accounts'), 'val' => $r[0]['expired']); - $accounts['expiring'] = array('label' => t('# expiring accounts'), 'val' => $r[0]['expiring']); + $accounts['total'] = array('label' => t('Accounts'), 'val' => $r[0]['total']); + $accounts['blocked'] = array('label' => t('Blocked accounts'), 'val' => $r[0]['blocked']); + $accounts['expired'] = array('label' => t('Expired accounts'), 'val' => $r[0]['expired']); + $accounts['expiring'] = array('label' => t('Expiring accounts'), 'val' => $r[0]['expiring']); } // pending registrations @@ -105,9 +105,9 @@ class Admin extends \Zotlabs\Web\Controller { $channels = array(); $r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0"); if ($r) { - $channels['total'] = array('label' => t('# Channels'), 'val' => $r[0]['total']); - $channels['main'] = array('label' => t('# primary'), 'val' => $r[0]['main']); - $channels['clones'] = array('label' => t('# clones'), 'val' => $r[0]['clones']); + $channels['total'] = array('label' => t('Channels'), 'val' => $r[0]['total']); + $channels['main'] = array('label' => t('Primary'), 'val' => $r[0]['main']); + $channels['clones'] = array('label' => t('Clones'), 'val' => $r[0]['clones']); } // We can do better, but this is a quick queue status @@ -118,14 +118,11 @@ class Admin extends \Zotlabs\Web\Controller { // If no plugins active return 0, otherwise list of plugin names $plugins = (count(\App::$plugins) == 0) ? count(\App::$plugins) : \App::$plugins; + if(is_array($plugins)) + sort($plugins); + // Could be extended to provide also other alerts to the admin $alertmsg = ''; - // annoy admin about upcoming unsupported PHP version - if (version_compare(PHP_VERSION, '5.4', '<')) { - $alertmsg = 'Your PHP version ' . PHP_VERSION . ' will not be supported with the next major release of $Projectname. You are strongly urged to upgrade to a current version.' - . '<br>PHP 5.3 has reached its <a href="http://php.net/eol.php" class="alert-link">End of Life (EOL)</a> in August 2014.' - . ' A list about current PHP versions can be found <a href="http://php.net/supported-versions.php" class="alert-link">here</a>.'; - } $vmaster = get_repository_version('master'); $vdev = get_repository_version('dev'); diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index d05e70aa9..4c5b82e78 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -17,7 +17,6 @@ class Site { check_form_security_token_redirectOnErr('/admin/site', 'admin_site'); $sitename = ((x($_POST,'sitename')) ? notags(trim($_POST['sitename'])) : ''); - $server_role = ((x($_POST,'server_role')) ? notags(trim($_POST['server_role'])) : 'standard'); $banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false); @@ -68,7 +67,6 @@ class Site { if(array_key_exists('techlevel', $_POST)) $techlevel = intval($_POST['techlevel']); - set_config('system', 'server_role', $server_role); set_config('system', 'feed_contacts', $feed_contacts); set_config('system', 'delivery_interval', $delivery_interval); set_config('system', 'delivery_batch_count', $delivery_batch_count); @@ -254,12 +252,6 @@ class Site { // now invert the logic for the setting. $discover_tab = (1 - $discover_tab); - $server_roles = [ - 'basic' => t('Basic/Minimal Social Networking'), - 'standard' => t('Standard Configuration (default)'), - 'pro' => t('Professional') - ]; - $techlevels = [ '0' => t('Beginner/Basic'), '1' => t('Novice - not skilled but willing to learn'), @@ -286,8 +278,6 @@ class Site { // name, label, value, help string, extra data... '$sitename' => array('sitename', t("Site name"), htmlspecialchars(get_config('system','sitename'), ENT_QUOTES, 'UTF-8'),''), - '$server_role' => array('server_role', t("Server Configuration/Role"), get_config('system','server_role'),'',$server_roles), - '$techlevel' => [ 'techlevel', t('Site default technical skill level'), get_config('system','techlevel'), t('Used to provide a member experience matched to technical comfort level'), $techlevels ], '$techlock' => [ 'techlock', t('Lock the technical skill level setting'), get_config('system','techlevel_lock'), t('Members can set their own technical comfort level by default') ], diff --git a/Zotlabs/Module/Authorize.php b/Zotlabs/Module/Authorize.php new file mode 100644 index 000000000..06f66c456 --- /dev/null +++ b/Zotlabs/Module/Authorize.php @@ -0,0 +1,71 @@ +<?php + +namespace Zotlabs\Module; + + +class Authorize extends \Zotlabs\Web\Controller { + + + function get() { + + + // workaround for HTTP-auth in CGI mode + if (x($_SERVER, 'REDIRECT_REMOTE_USER')) { + $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } + } + + if (x($_SERVER, 'HTTP_AUTHORIZATION')) { + $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } + } + + + + + require_once('include/oauth2.php'); + + $request = \OAuth2\Request::createFromGlobals(); + $response = new \OAuth2\Response(); + + // validate the authorize request + if (! $oauth2_server->validateAuthorizeRequest($request, $response)) { + $response->send(); + killme(); + } + + // display an authorization form + if (empty($_POST)) { + + return ' +<form method="post"> + <label>Do You Authorize TestClient?</label><br /> + <input type="submit" name="authorized" value="yes"> + <input type="submit" name="authorized" value="no"> +</form>'; + } + + // print the authorization code if the user has authorized your client + $is_authorized = ($_POST['authorized'] === 'yes'); + $oauth2_server->handleAuthorizeRequest($request, $response, $is_authorized); + if ($is_authorized) { + // this is only here so that you get to see your code in the cURL request. Otherwise, + // we'd redirect back to the client + $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40); + echo("SUCCESS! Authorization Code: $code"); + + } + + $response->send(); + killme(); + } + +}
\ No newline at end of file diff --git a/Zotlabs/Module/Block.php b/Zotlabs/Module/Block.php index e671730f6..d0fed44fe 100644 --- a/Zotlabs/Module/Block.php +++ b/Zotlabs/Module/Block.php @@ -3,8 +3,6 @@ namespace Zotlabs\Module; require_once('include/items.php'); require_once('include/conversation.php'); -require_once('include/page_widgets.php'); - class Block extends \Zotlabs\Web\Controller { diff --git a/Zotlabs/Module/Cdav.php b/Zotlabs/Module/Cdav.php new file mode 100644 index 000000000..f91dead04 --- /dev/null +++ b/Zotlabs/Module/Cdav.php @@ -0,0 +1,1202 @@ +<?php +namespace Zotlabs\Module; + +require_once('include/event.php'); + +class Cdav extends \Zotlabs\Web\Controller { + + function init() { + + if((argv(1) !== 'calendar') && (argv(1) !== 'addressbook')) { + + // workaround for HTTP-auth in CGI mode + if (x($_SERVER, 'REDIRECT_REMOTE_USER')) { + $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } + } + + if (x($_SERVER, 'HTTP_AUTHORIZATION')) { + $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } + } + + /** + * This server combines both CardDAV and CalDAV functionality into a single + * server. It is assumed that the server runs at the root of a HTTP domain (be + * that a domainname-based vhost or a specific TCP port. + * + * This example also assumes that you're using SQLite and the database has + * already been setup (along with the database tables). + * + * You may choose to use MySQL instead, just change the PDO connection + * statement. + */ + + /** + * UTC or GMT is easy to work with, and usually recommended for any + * application. + */ + date_default_timezone_set('UTC'); + + /** + * Make sure this setting is turned on and reflect the root url for your WebDAV + * server. + * + * This can be for example the root / or a complete path to your server script. + */ + + $baseUri = '/cdav/'; + + /** + * Database + * + */ + + $pdo = \DBA::$dba->db; + + // Autoloader + require_once 'vendor/autoload.php'; + + /** + * The backends. Yes we do really need all of them. + * + * This allows any developer to subclass just any of them and hook into their + * own backend systems. + */ + + $auth = new \Zotlabs\Storage\BasicAuth(); + $auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . 'CalDAV/CardDAV'); + + if (local_channel()) { + logger('loggedin'); + $channel = \App::get_channel(); + $auth->setCurrentUser($channel['channel_address']); + $auth->channel_id = $channel['channel_id']; + $auth->channel_hash = $channel['channel_hash']; + $auth->channel_account_id = $channel['channel_account_id']; + if($channel['channel_timezone']) + $auth->setTimezone($channel['channel_timezone']); + $auth->observer = $channel['channel_hash']; + } + + + $principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo); + $carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo); + $caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo); + + /** + * The directory tree + * + * Basically this is an array which contains the 'top-level' directories in the + * WebDAV server. + */ + + $nodes = [ + // /principals + new \Sabre\CalDAV\Principal\Collection($principalBackend), + // /calendars + new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend), + // /addressbook + new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend), + ]; + + // The object tree needs in turn to be passed to the server class + + $server = new \Sabre\DAV\Server($nodes); + + if(isset($baseUri)) + $server->setBaseUri($baseUri); + + // Plugins + $server->addPlugin(new \Sabre\DAV\Auth\Plugin($auth)); + //$server->addPlugin(new \Sabre\DAV\Browser\Plugin()); + $server->addPlugin(new \Sabre\DAV\Sync\Plugin()); + $server->addPlugin(new \Sabre\DAV\Sharing\Plugin()); + $server->addPlugin(new \Sabre\DAVACL\Plugin()); + + // CalDAV plugins + $server->addPlugin(new \Sabre\CalDAV\Plugin()); + $server->addPlugin(new \Sabre\CalDAV\SharingPlugin()); + //$server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin()); + $server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin()); + + // CardDAV plugins + $server->addPlugin(new \Sabre\CardDAV\Plugin()); + $server->addPlugin(new \Sabre\CardDAV\VCFExportPlugin()); + + // And off we go! + $server->exec(); + + killme(); + + } + + } + + function post() { + if(! local_channel()) + return; + + $channel = \App::get_channel(); + $principalUri = 'principals/' . $channel['channel_hash']; + + if(!cdav_principal($principalUri)) + return; + + $pdo = \DBA::$dba->db; + + require_once 'vendor/autoload.php'; + + if(argc() == 2 && argv(1) === 'calendar') { + + $caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo); + $calendars = $caldavBackend->getCalendarsForUser($principalUri); + + //create new calendar + if($_REQUEST['{DAV:}displayname'] && $_REQUEST['create']) { + do { + $duplicate = false; + $calendarUri = random_string(40); + + $r = q("SELECT uri FROM calendarinstances WHERE principaluri = '%s' AND uri = '%s' LIMIT 1", + dbesc($principalUri), + dbesc($calendarUri) + ); + + if (count($r)) + $duplicate = true; + } while ($duplicate == true); + + $properties = [ + '{DAV:}displayname' => $_REQUEST['{DAV:}displayname'], + '{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color'], + '{urn:ietf:params:xml:ns:caldav}calendar-description' => $channel['channel_name'] + ]; + + $id = $caldavBackend->createCalendar($principalUri, $calendarUri, $properties); + + // set new calendar to be visible + set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1); + } + + //create new calendar object via ajax request + if($_REQUEST['submit'] === 'create_event' && $_REQUEST['title'] && $_REQUEST['target'] && $_REQUEST['dtstart']) { + + $id = explode(':', $_REQUEST['target']); + + if(!cdav_perms($id[0],$calendars,true)) + return; + + $title = $_REQUEST['title']; + $dtstart = new \DateTime($_REQUEST['dtstart']); + if($_REQUEST['dtend']) + $dtend = new \DateTime($_REQUEST['dtend']); + $description = $_REQUEST['description']; + $location = $_REQUEST['location']; + + do { + $duplicate = false; + $objectUri = random_string(40) . '.ics'; + + $r = q("SELECT uri FROM calendarobjects WHERE calendarid = %s AND uri = '%s' LIMIT 1", + intval($id[0]), + dbesc($objectUri) + ); + + if (count($r)) + $duplicate = true; + } while ($duplicate == true); + + + $vcalendar = new \Sabre\VObject\Component\VCalendar([ + 'VEVENT' => [ + 'SUMMARY' => $title, + 'DTSTART' => $dtstart + ] + ]); + if($dtend) + $vcalendar->VEVENT->add('DTEND', $dtend); + if($description) + $vcalendar->VEVENT->add('DESCRIPTION', $description); + if($location) + $vcalendar->VEVENT->add('LOCATION', $location); + + $calendarData = $vcalendar->serialize(); + + $caldavBackend->createCalendarObject($id, $objectUri, $calendarData); + + killme(); + } + + //edit calendar name and color + if($_REQUEST['{DAV:}displayname'] && $_REQUEST['edit'] && $_REQUEST['id']) { + + $id = explode(':', $_REQUEST['id']); + + if(! cdav_perms($id[0],$calendars)) + return; + + $mutations = [ + '{DAV:}displayname' => $_REQUEST['{DAV:}displayname'], + '{http://apple.com/ns/ical/}calendar-color' => $_REQUEST['color'] + ]; + + $patch = new \Sabre\DAV\PropPatch($mutations); + + $caldavBackend->updateCalendar($id, $patch); + + $patch->commit(); + + } + + //edit calendar object via ajax request + if($_REQUEST['submit'] === 'update_event' && $_REQUEST['uri'] && $_REQUEST['title'] && $_REQUEST['target'] && $_REQUEST['dtstart']) { + + $id = explode(':', $_REQUEST['target']); + + if(!cdav_perms($id[0],$calendars,true)) + return; + + $uri = $_REQUEST['uri']; + $title = $_REQUEST['title']; + $dtstart = new \DateTime($_REQUEST['dtstart']); + $dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : ''; + $description = $_REQUEST['description']; + $location = $_REQUEST['location']; + + $object = $caldavBackend->getCalendarObject($id, $uri); + + $vcalendar = \Sabre\VObject\Reader::read($object['calendardata']); + + if($title) + $vcalendar->VEVENT->SUMMARY = $title; + if($dtstart) + $vcalendar->VEVENT->DTSTART = $dtstart; + if($dtend) + $vcalendar->VEVENT->DTEND = $dtend; + else + unset($vcalendar->VEVENT->DTEND); + if($description) + $vcalendar->VEVENT->DESCRIPTION = $description; + if($location) + $vcalendar->VEVENT->LOCATION = $location; + + $calendarData = $vcalendar->serialize(); + + $caldavBackend->updateCalendarObject($id, $uri, $calendarData); + + killme(); + } + + //delete calendar object via ajax request + if($_REQUEST['delete'] && $_REQUEST['uri'] && $_REQUEST['target']) { + + $id = explode(':', $_REQUEST['target']); + + if(!cdav_perms($id[0],$calendars,true)) + return; + + $uri = $_REQUEST['uri']; + + $caldavBackend->deleteCalendarObject($id, $uri); + + killme(); + } + + //edit calendar object date/timeme via ajax request (drag and drop) + if($_REQUEST['update'] && $_REQUEST['id'] && $_REQUEST['uri']) { + + $id = [$_REQUEST['id'][0], $_REQUEST['id'][1]]; + + if(!cdav_perms($id[0],$calendars,true)) + return; + + $uri = $_REQUEST['uri']; + $dtstart = new \DateTime($_REQUEST['dtstart']); + $dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : ''; + + $object = $caldavBackend->getCalendarObject($id, $uri); + + $vcalendar = \Sabre\VObject\Reader::read($object['calendardata']); + + if($dtstart) { + $vcalendar->VEVENT->DTSTART = $dtstart; + } + if($dtend) { + $vcalendar->VEVENT->DTEND = $dtend; + } + else { + unset($vcalendar->VEVENT->DTEND); + } + + $calendarData = $vcalendar->serialize(); + + $caldavBackend->updateCalendarObject($id, $uri, $calendarData); + + killme(); + } + + //share a calendar - this only works on local system (with channels on the same server) + if($_REQUEST['sharee'] && $_REQUEST['share']) { + + $id = [intval($_REQUEST['calendarid']), intval($_REQUEST['instanceid'])]; + + if(! cdav_perms($id[0],$calendars)) + return; + + $hash = $_REQUEST['sharee']; + + $sharee_arr = channelx_by_hash($hash); + + $sharee = new \Sabre\DAV\Xml\Element\Sharee(); + + $sharee->href = 'mailto:' . $sharee_arr['channel_hash']; + $sharee->principal = 'principals/' . $sharee_arr['channel_address']; + $sharee->access = intval($_REQUEST['access']); + $sharee->properties = ['{DAV:}displayname' => $channel['channel_name']]; + + $caldavBackend->updateInvites($id, [$sharee]); + } + } + + if(argc() >= 2 && argv(1) === 'addressbook') { + + $carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo); + $addressbooks = $carddavBackend->getAddressBooksForUser($principalUri); + + //create new addressbook + if($_REQUEST['{DAV:}displayname'] && $_REQUEST['create']) { + do { + $duplicate = false; + $addressbookUri = random_string(20); + + $r = q("SELECT uri FROM addressbooks WHERE principaluri = '%s' AND uri = '%s' LIMIT 1", + dbesc($principalUri), + dbesc($addressbookUri) + ); + + if (count($r)) + $duplicate = true; + } while ($duplicate == true); + + $properties = ['{DAV:}displayname' => $_REQUEST['{DAV:}displayname']]; + + $carddavBackend->createAddressBook($principalUri, $addressbookUri, $properties); + } + + //edit addressbook + if($_REQUEST['{DAV:}displayname'] && $_REQUEST['edit'] && intval($_REQUEST['id'])) { + + $id = $_REQUEST['id']; + + if(! cdav_perms($id,$addressbooks)) + return; + + $mutations = [ + '{DAV:}displayname' => $_REQUEST['{DAV:}displayname'] + ]; + + $patch = new \Sabre\DAV\PropPatch($mutations); + + $carddavBackend->updateAddressBook($id, $patch); + + $patch->commit(); + } + + //create addressbook card + if($_REQUEST['create'] && $_REQUEST['target'] && $_REQUEST['fn']) { + $id = $_REQUEST['target']; + + do { + $duplicate = false; + $uri = random_string(40) . '.vcf'; + + $r = q("SELECT uri FROM cards WHERE addressbookid = %s AND uri = '%s' LIMIT 1", + intval($id), + dbesc($uri) + ); + + if (count($r)) + $duplicate = true; + } while ($duplicate == true); + + //TODO: this mostly duplictes the procedure in update addressbook card. should move this part to a function to avoid duplication + $fn = $_REQUEST['fn']; + + $vcard = new \Sabre\VObject\Component\VCard([ + 'FN' => $fn, + 'N' => array_reverse(explode(' ', $fn)) + ]); + + $org = $_REQUEST['org']; + if($org) { + $vcard->ORG = $org; + } + + $title = $_REQUEST['title']; + if($title) { + $vcard->TITLE = $title; + } + + $tel = $_REQUEST['tel']; + $tel_type = $_REQUEST['tel_type']; + if($tel) { + $i = 0; + foreach($tel as $item) { + if($item) { + $vcard->add('TEL', $item, ['type' => $tel_type[$i]]); + } + $i++; + } + } + + $email = $_REQUEST['email']; + $email_type = $_REQUEST['email_type']; + if($email) { + $i = 0; + foreach($email as $item) { + if($item) { + $vcard->add('EMAIL', $item, ['type' => $email_type[$i]]); + } + $i++; + } + } + + $impp = $_REQUEST['impp']; + $impp_type = $_REQUEST['impp_type']; + if($impp) { + $i = 0; + foreach($impp as $item) { + if($item) { + $vcard->add('IMPP', $item, ['type' => $impp_type[$i]]); + } + $i++; + } + } + + $url = $_REQUEST['url']; + $url_type = $_REQUEST['url_type']; + if($url) { + $i = 0; + foreach($url as $item) { + if($item) { + $vcard->add('URL', $item, ['type' => $url_type[$i]]); + } + $i++; + } + } + + $adr = $_REQUEST['adr']; + $adr_type = $_REQUEST['adr_type']; + + if($adr) { + $i = 0; + foreach($adr as $item) { + if($item) { + $vcard->add('ADR', $item, ['type' => $adr_type[$i]]); + } + $i++; + } + } + + $note = $_REQUEST['note']; + if($note) { + $vcard->NOTE = $note; + } + + $cardData = $vcard->serialize(); + + $carddavBackend->createCard($id, $uri, $cardData); + + } + + //edit addressbook card + if($_REQUEST['update'] && $_REQUEST['uri'] && $_REQUEST['target']) { + + $id = $_REQUEST['target']; + + if(!cdav_perms($id,$addressbooks)) + return; + + $uri = $_REQUEST['uri']; + + $object = $carddavBackend->getCard($id, $uri); + $vcard = \Sabre\VObject\Reader::read($object['carddata']); + + $fn = $_REQUEST['fn']; + if($fn) { + $vcard->FN = $fn; + $vcard->N = array_reverse(explode(' ', $fn)); + } + + $org = $_REQUEST['org']; + if($org) { + $vcard->ORG = $org; + } + else { + unset($vcard->ORG); + } + + $title = $_REQUEST['title']; + if($title) { + $vcard->TITLE = $title; + } + else { + unset($vcard->TITLE); + } + + $tel = $_REQUEST['tel']; + $tel_type = $_REQUEST['tel_type']; + if($tel) { + $i = 0; + unset($vcard->TEL); + foreach($tel as $item) { + if($item) { + $vcard->add('TEL', $item, ['type' => $tel_type[$i]]); + } + $i++; + } + } + else { + unset($vcard->TEL); + } + + $email = $_REQUEST['email']; + $email_type = $_REQUEST['email_type']; + if($email) { + $i = 0; + unset($vcard->EMAIL); + foreach($email as $item) { + if($item) { + $vcard->add('EMAIL', $item, ['type' => $email_type[$i]]); + } + $i++; + } + } + else { + unset($vcard->EMAIL); + } + + $impp = $_REQUEST['impp']; + $impp_type = $_REQUEST['impp_type']; + if($impp) { + $i = 0; + unset($vcard->IMPP); + foreach($impp as $item) { + if($item) { + $vcard->add('IMPP', $item, ['type' => $impp_type[$i]]); + } + $i++; + } + } + else { + unset($vcard->IMPP); + } + + $url = $_REQUEST['url']; + $url_type = $_REQUEST['url_type']; + if($url) { + $i = 0; + unset($vcard->URL); + foreach($url as $item) { + if($item) { + $vcard->add('URL', $item, ['type' => $url_type[$i]]); + } + $i++; + } + } + else { + unset($vcard->URL); + } + + $adr = $_REQUEST['adr']; + $adr_type = $_REQUEST['adr_type']; + if($adr) { + $i = 0; + unset($vcard->ADR); + foreach($adr as $item) { + if($item) { + $vcard->add('ADR', $item, ['type' => $adr_type[$i]]); + } + $i++; + } + } + else { + unset($vcard->ADR); + } + + $note = $_REQUEST['note']; + if($note) { + $vcard->NOTE = $note; + } + else { + unset($vcard->NOTE); + } + + $cardData = $vcard->serialize(); + + $carddavBackend->updateCard($id, $uri, $cardData); + } + + //delete addressbook card + if($_REQUEST['delete'] && $_REQUEST['uri'] && $_REQUEST['target']) { + + $id = $_REQUEST['target']; + + if(!cdav_perms($id,$addressbooks)) + return; + + $uri = $_REQUEST['uri']; + + $carddavBackend->deleteCard($id, $uri); + } + } + + //Import calendar or addressbook + if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size']) && $_REQUEST['target']) { + + $src = @file_get_contents($_FILES['userfile']['tmp_name']); + + if($src) { + + if($_REQUEST['c_upload']) { + $id = explode(':', $_REQUEST['target']); + $ext = 'ics'; + $table = 'calendarobjects'; + $column = 'calendarid'; + $objects = new \Sabre\VObject\Splitter\ICalendar($src); + $profile = \Sabre\VObject\Node::PROFILE_CALDAV; + $backend = new \Sabre\CalDAV\Backend\PDO($pdo); + } + + if($_REQUEST['a_upload']) { + $id[] = intval($_REQUEST['target']); + $ext = 'vcf'; + $table = 'cards'; + $column = 'addressbookid'; + $objects = new \Sabre\VObject\Splitter\VCard($src); + $profile = \Sabre\VObject\Node::PROFILE_CARDDAV; + $backend = new \Sabre\CardDAV\Backend\PDO($pdo); + } + + while ($object = $objects->getNext()) { + + if($_REQUEST['a_upload']) { + $object = $object->convert(\Sabre\VObject\Document::VCARD40); + } + + $ret = $object->validate($profile & \Sabre\VObject\Node::REPAIR); + + //level 3 Means that the document is invalid, + //level 2 means a warning. A warning means it's valid but it could cause interopability issues, + //level 1 means that there was a problem earlier, but the problem was automatically repaired. + + if($ret[0]['level'] < 3) { + do { + $duplicate = false; + $objectUri = random_string(40) . '.' . $ext; + + $r = q("SELECT uri FROM $table WHERE $column = %d AND uri = '%s' LIMIT 1", + dbesc($id[0]), + dbesc($objectUri) + ); + + if (count($r)) + $duplicate = true; + } while ($duplicate == true); + + if($_REQUEST['c_upload']) { + $backend->createCalendarObject($id, $objectUri, $object->serialize()); + } + + if($_REQUEST['a_upload']) { + $backend->createCard($id[0], $objectUri, $object->serialize()); + } + } + else { + if($_REQUEST['c_upload']) { + notice( '<strong>' . t('INVALID EVENT DISMISSED!') . '</strong>' . EOL . + '<strong>' . t('Summary: ') . '</strong>' . (($object->VEVENT->SUMMARY) ? $object->VEVENT->SUMMARY : t('Unknown')) . EOL . + '<strong>' . t('Date: ') . '</strong>' . (($object->VEVENT->DTSTART) ? $object->VEVENT->DTSTART : t('Unknown')) . EOL . + '<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL + ); + } + + if($_REQUEST['a_upload']) { + notice( '<strong>' . t('INVALID CARD DISMISSED!') . '</strong>' . EOL . + '<strong>' . t('Name: ') . '</strong>' . (($object->FN) ? $object->FN : t('Unknown')) . EOL . + '<strong>' . t('Reason: ') . '</strong>' . $ret[0]['message'] . EOL + ); + } + } + } + } + @unlink($src); + } + } + + function get() { + + if(!local_channel()) + return; + + $channel = \App::get_channel(); + $principalUri = 'principals/' . $channel['channel_hash']; + + + if(!cdav_principal($principalUri)) { + $this->activate($channel); + if(!cdav_principal($principalUri)) { + return; + } + } + + $pdo = \DBA::$dba->db; + + require_once 'vendor/autoload.php'; + + head_add_css('cdav.css'); + + if(argv(1) === 'calendar') { + $caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo); + $calendars = $caldavBackend->getCalendarsForUser($principalUri); + } + + //Display calendar(s) here + if(argc() == 2 && argv(1) === 'calendar') { + + head_add_css('/library/fullcalendar/fullcalendar.css'); + head_add_css('cdav_calendar.css'); + + head_add_js('/library/moment/moment.min.js', 1); + head_add_js('/library/fullcalendar/fullcalendar.min.js', 1); + head_add_js('/library/fullcalendar/locale-all.js', 1); + + foreach($calendars as $calendar) { + $editable = (($calendar['share-access'] == 2) ? 'false' : 'true'); // false/true must be string since we're passing it to javascript + $color = (($calendar['{http://apple.com/ns/ical/}calendar-color']) ? $calendar['{http://apple.com/ns/ical/}calendar-color'] : '#3a87ad'); + $sharer = (($calendar['share-access'] == 3) ? $calendar['{urn:ietf:params:xml:ns:caldav}calendar-description'] : ''); + $switch = get_pconfig(local_channel(), 'cdav_calendar', $calendar['id'][0]); + if($switch) { + $sources .= '{ + url: \'/cdav/calendar/json/' . $calendar['id'][0] . '/' . $calendar['id'][1] . '\', + color: \'' . $color . '\' + }, '; + } + + if($calendar['share-access'] != 2) { + $writable_calendars[] = [ + 'displayname' => $calendar['{DAV:}displayname'], + 'sharer' => $sharer, + 'id' => $calendar['id'] + ]; + } + } + + $sources = rtrim($sources, ', '); + + $first_day = get_pconfig(local_channel(),'system','cal_first_day'); + $first_day = (($first_day) ? $first_day : 0); + + $title = ['title', t('Event title')]; + $dtstart = ['dtstart', t('Start date and time'), '', t('Example: YYYY-MM-DD HH:mm')]; + $dtend = ['dtend', t('End date and time'), '', t('Example: YYYY-MM-DD HH:mm')]; + $description = ['description', t('Description')]; + $location = ['location', t('Location')]; + + $o .= replace_macros(get_markup_template('cdav_calendar.tpl'), [ + '$sources' => $sources, + '$color' => $color, + '$lang' => \App::$language, + '$first_day' => $first_day, + '$prev' => t('Previous'), + '$next' => t('Next'), + '$today' => t('Today'), + '$month' => t('Month'), + '$week' => t('Week'), + '$day' => t('Day'), + '$list_month' => t('List month'), + '$list_week' => t('List week'), + '$list_day' => t('List day'), + '$title' => $title, + '$writable_calendars' => $writable_calendars, + '$dtstart' => $dtstart, + '$dtend' => $dtend, + '$description' => $description, + '$location' => $location, + '$more' => t('More'), + '$less' => t('Less'), + '$calendar_select_label' => t('Select calendar'), + '$delete' => t('Delete'), + '$delete_all' => t('Delete all'), + '$cancel' => t('Cancel'), + '$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.') + ]); + + return $o; + + } + + //Provide json data for calendar + if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'json' && intval(argv(3)) && intval(argv(4))) { + + $id = [argv(3), argv(4)]; + + if(! cdav_perms($id[0],$calendars)) + killme(); + + if (x($_GET,'start')) + $start = new \DateTime($_GET['start']); + if (x($_GET,'end')) + $end = new \DateTime($_GET['end']); + + $filters['name'] = 'VCALENDAR'; + $filters['prop-filters'][0]['name'] = 'VEVENT'; + $filters['comp-filters'][0]['name'] = 'VEVENT'; + $filters['comp-filters'][0]['time-range']['start'] = $start; + $filters['comp-filters'][0]['time-range']['end'] = $end; + + $uris = $caldavBackend->calendarQuery($id, $filters); + if($uris) { + + $objects = $caldavBackend->getMultipleCalendarObjects($id, $uris); + + foreach($objects as $object) { + + $vcalendar = \Sabre\VObject\Reader::read($object['calendardata']); + + if(isset($vcalendar->VEVENT->RRULE)) + $vcalendar = $vcalendar->expand($start, $end); + + foreach($vcalendar->VEVENT as $vevent) { + $title = (string)$vevent->SUMMARY; + $dtstart = (string)$vevent->DTSTART; + $dtend = (string)$vevent->DTEND; + $description = (string)$vevent->DESCRIPTION; + $location = (string)$vevent->LOCATION; + + $rw = ((cdav_perms($id[0],$calendars,true)) ? true : false); + $recurrent = ((isset($vevent->{'RECURRENCE-ID'})) ? true : false); + + $editable = $rw ? true : false; + + if($recurrent) + $editable = false; + + $allDay = false; + + // allDay event rules + if(!strpos($dtstart, 'T') && !strpos($dtend, 'T')) + $allDay = true; + if(strpos($dtstart, 'T000000') && strpos($dtend, 'T000000')) + $allDay = true; + + $events[] = [ + 'calendar_id' => $id, + 'uri' => $object['uri'], + 'title' => $title, + 'start' => $dtstart, + 'end' => $dtend, + 'description' => $description, + 'location' => $location, + 'allDay' => $allDay, + 'editable' => $editable, + 'recurrent' => $recurrent, + 'rw' => $rw + ]; + } + } + json_return_and_die($events); + } + else { + killme(); + } + } + + //enable/disable calendars + if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'switch' && intval(argv(3)) && (argv(4) == 1 || argv(4) == 0)) { + $id = argv(3); + + if(! cdav_perms($id,$calendars)) + killme(); + + set_pconfig(local_channel(), 'cdav_calendar' , argv(3), argv(4)); + killme(); + } + + //drop calendar + if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'drop' && intval(argv(3)) && intval(argv(4))) { + $id = [argv(3), argv(4)]; + + if(! cdav_perms($id[0],$calendars)) + killme(); + + $caldavBackend->deleteCalendar($id); + killme(); + } + + //drop sharee + if(argc() == 6 && argv(1) === 'calendar' && argv(2) === 'dropsharee' && intval(argv(3)) && intval(argv(4))) { + + $id = [argv(3), argv(4)]; + $hash = argv(5); + + if(! cdav_perms($id[0],$calendars)) + killme(); + + $sharee_arr = channelx_by_hash($hash); + + $sharee = new \Sabre\DAV\Xml\Element\Sharee(); + + $sharee->href = 'mailto:' . $sharee_arr['channel_hash']; + $sharee->principal = 'principals/' . $sharee_arr['channel_address']; + $sharee->access = 4; + $caldavBackend->updateInvites($id, [$sharee]); + + killme(); + } + + + if(argv(1) === 'addressbook') { + $carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo); + $addressbooks = $carddavBackend->getAddressBooksForUser($principalUri); + } + + //Display Adressbook here + if(argc() == 3 && argv(1) === 'addressbook' && intval(argv(2))) { + + $id = argv(2); + + $displayname = cdav_perms($id,$addressbooks); + + if(!$displayname) + return; + + head_add_css('cdav_addressbook.css'); + + $o = ''; + + $sabrecards = $carddavBackend->getCards($id); + foreach($sabrecards as $sabrecard) { + $uris[] = $sabrecard['uri']; + } + + if($uris) { + $objects = $carddavBackend->getMultipleCards($id, $uris); + + foreach($objects as $object) { + $vcard = \Sabre\VObject\Reader::read($object['carddata']); + + $photo = ''; + if($vcard->PHOTO) { + $photo_value = strtolower($vcard->PHOTO->getValueType()); // binary or uri + if($photo_value === 'binary') { + $photo_type = strtolower($vcard->PHOTO['TYPE']); // mime jpeg, png or gif + $photo = 'data:image/' . $photo_type . ';base64,' . base64_encode((string)$vcard->PHOTO); + } + else { + $url = parse_url((string)$vcard->PHOTO); + $photo = 'data:' . $url['path']; + } + } + + $fn = ''; + if($vcard->FN) { + $fn = (string)$vcard->FN; + } + + $org = ''; + if($vcard->ORG) { + $org = (string)$vcard->ORG; + } + + $title = ''; + if($vcard->TITLE) { + $title = (string)$vcard->TITLE; + } + + $tels = []; + if($vcard->TEL) { + foreach($vcard->TEL as $tel) { + $type = (($tel['TYPE']) ? translate_type((string)$tel['TYPE']) : ''); + $tels[] = [ + 'type' => $type, + 'nr' => (string)$tel + ]; + } + } + + $emails = []; + if($vcard->EMAIL) { + foreach($vcard->EMAIL as $email) { + $type = (($email['TYPE']) ? translate_type((string)$email['TYPE']) : ''); + $emails[] = [ + 'type' => $type, + 'address' => (string)$email + ]; + } + } + + $impps = []; + if($vcard->IMPP) { + foreach($vcard->IMPP as $impp) { + $type = (($impp['TYPE']) ? translate_type((string)$impp['TYPE']) : ''); + $impps[] = [ + 'type' => $type, + 'address' => (string)$impp + ]; + } + } + + $urls = []; + if($vcard->URL) { + foreach($vcard->URL as $url) { + $type = (($url['TYPE']) ? translate_type((string)$url['TYPE']) : ''); + $urls[] = [ + 'type' => $type, + 'address' => (string)$url + ]; + } + } + + $adrs = []; + if($vcard->ADR) { + foreach($vcard->ADR as $adr) { + $type = (($adr['TYPE']) ? translate_type((string)$adr['TYPE']) : ''); + $adrs[] = [ + 'type' => $type, + 'address' => $adr->getParts() + ]; + } + } + + $note = ''; + if($vcard->NOTE) { + $note = (string)$vcard->NOTE; + } + + $cards[] = [ + 'id' => $object['id'], + 'uri' => $object['uri'], + + 'photo' => $photo, + 'fn' => $fn, + 'org' => $org, + 'title' => $title, + 'tels' => $tels, + 'emails' => $emails, + 'impps' => $impps, + 'urls' => $urls, + 'adrs' => $adrs, + 'note' => $note + ]; + } + + usort($cards, function($a, $b) { return strcasecmp($a['fn'], $b['fn']); }); + } + + $o .= replace_macros(get_markup_template('cdav_addressbook.tpl'), [ + '$id' => $id, + '$cards' => $cards, + '$displayname' => $displayname, + '$name_label' => t('Name'), + '$org_label' => t('Organisation'), + '$title_label' => t('Title'), + '$tel_label' => t('Phone'), + '$email_label' => t('Email'), + '$impp_label' => t('Instant messenger'), + '$url_label' => t('Website'), + '$adr_label' => t('Address'), + '$note_label' => t('Note'), + '$mobile' => t('Mobile'), + '$home' => t('Home'), + '$work' => t('Work'), + '$other' => t('Other'), + '$add_card' => t('Add Contact'), + '$add_field' => t('Add Field'), + '$create' => t('Create'), + '$update' => t('Update'), + '$delete' => t('Delete'), + '$cancel' => t('Cancel'), + '$po_box' => t('P.O. Box'), + '$extra' => t('Additional'), + '$street' => t('Street'), + '$locality' => t('Locality'), + '$region' => t('Region'), + '$zip_code' => t('ZIP Code'), + '$country' => t('Country') + ]); + + return $o; + } + + //delete addressbook + if(argc() > 3 && argv(1) === 'addressbook' && argv(2) === 'drop' && intval(argv(3))) { + $id = argv(3); + + if(! cdav_perms($id,$addressbooks)) + return; + + $carddavBackend->deleteAddressBook($id); + killme(); + } + + } + + function activate($channel) { + + if(! $channel) + return; + + $uri = 'principals/' . $channel['channel_hash']; + + + $r = q("select * from principals where uri = '%s' limit 1", + dbesc($uri) + ); + if($r) { + $r = q("update principals set email = '%s', displayname = '%s' where uri = '%s' ", + dbesc($channel['xchan_addr']), + dbesc($channel['channel_name']), + dbesc($uri) + ); + } + else { + $r = q("insert into principals ( uri, email, displayname ) values('%s','%s','%s') ", + dbesc($uri), + dbesc($channel['xchan_addr']), + dbesc($channel['channel_name']) + ); + + //create default calendar + $r = q("insert into calendars (components) values('%s') ", + dbesc('VEVENT,VTODO') + ); + + $r = q("insert into calendarinstances (principaluri, displayname, uri, description, calendarcolor) values( '%s', '%s', '%s', '%s', '%s') ", + dbesc($uri), + dbesc(t('Default Calendar')), + dbesc('default'), + dbesc($channel['channel_name']), + dbesc('#3a87ad') + ); + + //create default addressbook + $r = q("insert into addressbooks (principaluri, displayname, uri) values('%s', '%s', '%s') ", + dbesc($uri), + dbesc(t('Default Addressbook')), + dbesc('default') + ); + } + } + + +} diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 98a1e6c88..51c937270 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -365,10 +365,10 @@ class Channel extends \Zotlabs\Web\Controller { if($checkjs->disabled()) { - $o .= conversation($a,$items,'channel',$update,'traditional'); + $o .= conversation($items,'channel',$update,'traditional'); } else { - $o .= conversation($a,$items,'channel',$update,$page_mode); + $o .= conversation($items,'channel',$update,$page_mode); } if((! $update) || ($checkjs->disabled())) { diff --git a/Zotlabs/Module/Chanview.php b/Zotlabs/Module/Chanview.php index 01ee74d5a..24ab9b022 100644 --- a/Zotlabs/Module/Chanview.php +++ b/Zotlabs/Module/Chanview.php @@ -102,27 +102,32 @@ class Chanview extends \Zotlabs\Web\Controller { } $is_zot = false; + $connected = false; if (\App::$poi) { $url = \App::$poi['xchan_url']; if(\App::$poi['xchan_network'] === 'zot') { $is_zot = true; } + if(local_channel()) { + $c = q("select abook_id from abook where abook_channel = %d and abook_xchan = '%s' limit 1", + intval(local_channel()), + dbesc(\App::$poi['xchan_hash']) + ); + if($c) + $connected = true; + } } - + // We will load the chanview template if it's a foreign network, // just so that we can provide a connect button along with a profile // photo. Chances are we can't load the remote profile into an iframe // because of cross-domain security headers. So provide a link to // the remote profile. - + // If we are already connected, just go to the profile. // Zot channels will usually have a connect link. - // If it isn't zot, 'pro' members won't be able to use the connect - // button as it is a foreign network so just send them to the remote - // profile. - - if($is_zot || \Zotlabs\Lib\System::get_server_role() === 'pro') { + if($is_zot || $connected) { if($is_zot && $observer) { $url = zid($url); } diff --git a/Zotlabs/Module/Cloud.php b/Zotlabs/Module/Cloud.php index 7370eeda3..75191a279 100644 --- a/Zotlabs/Module/Cloud.php +++ b/Zotlabs/Module/Cloud.php @@ -86,12 +86,13 @@ class Cloud extends \Zotlabs\Web\Controller { // require_once('\Zotlabs\Storage/QuotaPlugin.php'); // $server->addPlugin(new \Zotlabs\Storage\\QuotaPlugin($auth)); - ob_start(); +// ob_start(); // All we need to do now, is to fire up the server $server->exec(); - ob_end_flush(); - +// ob_end_flush(); + if($browser->build_page) + construct_page(); killme(); } diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index b079ae860..b3c5e8ee9 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -19,7 +19,7 @@ class Connections extends \Zotlabs\Web\Controller { } - function get() { + function get() { $sort_type = 0; $o = ''; @@ -63,8 +63,8 @@ class Connections extends \Zotlabs\Web\Controller { $hidden = true; break; case 'archived': - $search_flags = " and abook_archived = 1 "; - $head = t('Archived'); + $search_flags = " and ( abook_archived = 1 OR abook_not_here = 1) "; + $head = t('Archived/Unreachable'); $archived = true; break; case 'pending': @@ -168,10 +168,10 @@ class Connections extends \Zotlabs\Web\Controller { ), 'archived' => array( - 'label' => t('Archived'), + 'label' => t('Archived/Unreachable'), 'url' => z_root() . '/connections/archived', 'sel' => ($archived) ? 'active' : '', - 'title' => t('Only show archived connections'), + 'title' => t('Only show archived/unreachable connections'), ), 'hidden' => array( @@ -243,7 +243,8 @@ class Connections extends \Zotlabs\Web\Controller { ((intval($rr['abook_archived'])) ? t('Archived') : ''), ((intval($rr['abook_hidden'])) ? t('Hidden') : ''), ((intval($rr['abook_ignored'])) ? t('Ignored') : ''), - ((intval($rr['abook_blocked'])) ? t('Blocked') : '') + ((intval($rr['abook_blocked'])) ? t('Blocked') : ''), + ((intval($rr['abook_not_here'])) ? t('Not connected at this location') : '') ); foreach($status as $str) { @@ -257,11 +258,12 @@ class Connections extends \Zotlabs\Web\Controller { $contacts[] = array( 'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']), 'edit_hover' => t('Edit connection'), + 'edit' => t('Edit'), 'delete_hover' => t('Delete connection'), 'id' => $rr['abook_id'], 'thumb' => $rr['xchan_photo_m'], 'name' => $rr['xchan_name'], - 'classes' => (intval($rr['abook_archived']) ? 'archived' : ''), + 'classes' => ((intval($rr['abook_archived']) || intval($rr['abook_not_here'])) ? 'archived' : ''), 'link' => z_root() . '/connedit/' . $rr['abook_id'], 'deletelink' => z_root() . '/connedit/' . intval($rr['abook_id']) . '/drop', 'delete' => t('Delete'), diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index 484e69b52..d301c2d45 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -842,6 +842,22 @@ class Connedit extends \Zotlabs\Web\Controller { } else $locstr = t('none'); + + $clone_warn = ''; + $clonable = (in_array($contact['xchan_network'],['zot','rss']) ? true : false); + if(! $clonable) { + $clone_warn = '<strong>'; + $clone_warn .= ((intval($contact['abook_not_here'])) + ? t('This connection is unreachable from this location.') + : t('This connection may be unreachable from other channel locations.') + ); + $clone_warn .= '</strong><br>' . t('Location independence is not supported by their network.'); + } + + + + if(intval($contact['abook_not_here']) && $unclonable) + $not_here = t('This connection is unreachable from this location. Location independence is not supported by their network.'); $o .= replace_macros($tpl, [ '$header' => (($self) ? t('Connection Default Permissions') : sprintf( t('Connection: %s'),$contact['xchan_name'])), @@ -856,6 +872,7 @@ class Connedit extends \Zotlabs\Web\Controller { '$addr_text' => t('This connection\'s primary address is'), '$loc_text' => t('Available locations:'), '$locstr' => $locstr, + '$unclonable' => $clone_warn, '$notself' => (($self) ? '' : '1'), '$self' => (($self) ? '1' : ''), '$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'), diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index 815672091..df3cb1e2b 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -308,12 +308,12 @@ class Display extends \Zotlabs\Web\Controller { if ($checkjs->disabled()) { - $o .= conversation($a, $items, 'display', $update, 'traditional'); + $o .= conversation($items, 'display', $update, 'traditional'); if ($items[0]['title']) \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title']; } else { - $o .= conversation($a, $items, 'display', $update, 'client'); + $o .= conversation($items, 'display', $update, 'client'); } if($updateable) { diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php index 629bdd3fd..a54c42e7f 100644 --- a/Zotlabs/Module/Editpost.php +++ b/Zotlabs/Module/Editpost.php @@ -39,6 +39,11 @@ class Editpost extends \Zotlabs\Web\Controller { return; } + if($itm[0]['resource_type'] === 'photo' && $itm[0]['resource_id']) { + notice( t('Item is not editable') . EOL); + return; + } + if($itm[0]['resource_type'] === 'event' && $itm[0]['resource_id']) { goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1'); } diff --git a/Zotlabs/Module/Hcard.php b/Zotlabs/Module/Hcard.php index 13097939e..912c84fd2 100644 --- a/Zotlabs/Module/Hcard.php +++ b/Zotlabs/Module/Hcard.php @@ -14,6 +14,8 @@ class Hcard extends \Zotlabs\Web\Controller { return; } + logger('hcard_request: ' . $which, LOGGER_DEBUG); + $profile = ''; $channel = \App::get_channel(); diff --git a/Zotlabs/Module/Help.php b/Zotlabs/Module/Help.php index e247416d9..0373a4aab 100644 --- a/Zotlabs/Module/Help.php +++ b/Zotlabs/Module/Help.php @@ -44,42 +44,42 @@ class Help extends \Zotlabs\Web\Controller { return $o; } - - - if(argc() > 2 && argv(argc()-2) === 'assets') { - $path = ''; - for($x = 1; $x < argc(); $x ++) { - if(strlen($path)) - $path .= '/'; - $path .= argv($x); - } - $realpath = 'doc/' . $path; - //Set the content-type header as appropriate - $imageInfo = getimagesize($realpath); - switch ($imageInfo[2]) { - case IMAGETYPE_JPEG: - header("Content-Type: image/jpeg"); - break; - case IMAGETYPE_GIF: - header("Content-Type: image/gif"); - break; - case IMAGETYPE_PNG: - header("Content-Type: image/png"); - break; - default: - break; - } - header("Content-Length: " . filesize($realpath)); + + + if(argc() > 2 && argv(argc()-2) === 'assets') { + $path = ''; + for($x = 1; $x < argc(); $x ++) { + if(strlen($path)) + $path .= '/'; + $path .= argv($x); + } + $realpath = 'doc/' . $path; + //Set the content-type header as appropriate + $imageInfo = getimagesize($realpath); + switch ($imageInfo[2]) { + case IMAGETYPE_JPEG: + header("Content-Type: image/jpeg"); + break; + case IMAGETYPE_GIF: + header("Content-Type: image/gif"); + break; + case IMAGETYPE_PNG: + header("Content-Type: image/png"); + break; + default: + break; + } + header("Content-Length: " . filesize($realpath)); - // dump the picture and stop the script - readfile($realpath); - killme(); - } + // dump the picture and stop the script + readfile($realpath); + killme(); + } $headings = [ - 'about' => t('About'), - 'member' => t('Members'), - 'admin' => t('Administrators'), + 'about' => t('About'), + 'member' => t('Members'), + 'admin' => t('Administrators'), 'developer' => t('Developers'), 'tutorials' => t('Tutorials') ]; @@ -87,13 +87,13 @@ class Help extends \Zotlabs\Web\Controller { if(array_key_exists(argv(1), $headings)) $heading = $headings[argv(1)]; - $content = get_help_content(); + $content = get_help_content(); return replace_macros(get_markup_template('help.tpl'), array( - '$title' => t('$Projectname Documentation'), + '$title' => t('$Projectname Documentation'), '$tocHeading' => t('Contents'), - '$content' => $content, - '$heading' => $heading + '$content' => $content, + '$heading' => $heading )); } diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php index ce3fd469a..40ce8f6d1 100644 --- a/Zotlabs/Module/Import.php +++ b/Zotlabs/Module/Import.php @@ -121,8 +121,7 @@ class Import extends \Zotlabs\Web\Controller { $t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 ); notice($t); } - if(array_key_exists('server_role',$data['compatibility']) && $data['compatibility']['server_role'] == 'basic') - $moving = true; + } if($moving) @@ -333,6 +332,10 @@ class Import extends \Zotlabs\Web\Controller { $abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0); } + if(array_key_exists('abook_instance',$abook) && $abook['abook_instance'] && strpos($abook['abook_instance'],z_root()) === false) { + $abook['abook_not_here'] = 1; + } + if($abook['abook_self']) { $role = get_pconfig($channel['channel_id'],'system','permissions_role'); if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) { diff --git a/Zotlabs/Module/Invite.php b/Zotlabs/Module/Invite.php index 6b6f80a31..927e7beae 100644 --- a/Zotlabs/Module/Invite.php +++ b/Zotlabs/Module/Invite.php @@ -49,7 +49,7 @@ class Invite extends \Zotlabs\Web\Controller { if(! $recip) continue; - if(! valid_email($recip)) { + if(! validate_email($recip)) { notice( sprintf( t('%s : Not a valid email address.'), $recip) . EOL); continue; } diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 952ecf487..e96d4c669 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -818,7 +818,7 @@ class Item extends \Zotlabs\Web\Controller { $datarray['owner'] = $owner_xchan; $datarray['author'] = $observer; $datarray['attach'] = json_encode($datarray['attach']); - $o = conversation($a,array($datarray),'search',false,'preview'); + $o = conversation(array($datarray),'search',false,'preview'); // logger('preview: ' . $o, LOGGER_DEBUG); echo json_encode(array('preview' => $o)); killme(); diff --git a/Zotlabs/Module/Moderate.php b/Zotlabs/Module/Moderate.php index 92df58858..9af43420d 100644 --- a/Zotlabs/Module/Moderate.php +++ b/Zotlabs/Module/Moderate.php @@ -68,8 +68,7 @@ class Moderate extends \Zotlabs\Web\Controller { $items = array(); } - $o = conversation($a,$items,'moderate',false,'traditional'); - + $o = conversation($items,'moderate',false,'traditional'); return $o; } diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 1c7c70019..f2ad77dd7 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -551,7 +551,7 @@ class Network extends \Zotlabs\Web\Controller { $mode = (($nouveau) ? 'network-new' : 'network'); - $o .= conversation($a,$items,$mode,$update,$page_mode); + $o .= conversation($items,$mode,$update,$page_mode); if(($items) && (! $update)) $o .= alt_pager($a,count($items)); diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index 8e6fd1d37..cfd45e909 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -134,7 +134,7 @@ class New_channel extends \Zotlabs\Web\Controller { $name = array('name', t('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"'), "*"); $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/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 role with your privacy requirements.') . ' <a href="help/member/member_guide#Account_Permission_Roles" target="_blank">' . t('Read more about roles') . '</a>',$perm_roles); $o = replace_macros(get_markup_template('new_channel.tpl'), array( '$title' => t('Create Channel'), diff --git a/Zotlabs/Module/Page.php b/Zotlabs/Module/Page.php index 7bc90c091..c142afe77 100644 --- a/Zotlabs/Module/Page.php +++ b/Zotlabs/Module/Page.php @@ -3,7 +3,6 @@ namespace Zotlabs\Module; require_once('include/items.php'); require_once('include/conversation.php'); -require_once('include/page_widgets.php'); class Page extends \Zotlabs\Web\Controller { diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index dc4ae670e..8a110f925 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -154,7 +154,9 @@ class Photo extends \Zotlabs\Web\Controller { intval($resolution) ); - if($r && $r[0]['photo_usage'] == PHOTO_COVER) + // viewing cover photos is allowed unless a plugin chooses to block it. + + if($r && intval($r[0]['photo_usage']) === PHOTO_COVER && $resolution >= PHOTO_RES_COVER_1200) $allowed = 1; $d = [ 'imgscale' => $resolution, 'resource_id' => $photo, 'photo' => $r, 'allowed' => $allowed ]; diff --git a/Zotlabs/Module/Poke.php b/Zotlabs/Module/Poke.php index cf8d83023..ea50e821a 100644 --- a/Zotlabs/Module/Poke.php +++ b/Zotlabs/Module/Poke.php @@ -41,7 +41,10 @@ class Poke extends \Zotlabs\Web\Controller { $activity = ACTIVITY_POKE . '#' . urlencode($verbs[$verb][0]); $contact_id = intval($_REQUEST['cid']); - if(! $contact_id) + + $xchan = trim($_REQUEST['xchan']); + + if(! ($contact_id || $xchan)) return; $parent = ((x($_REQUEST,'parent')) ? intval($_REQUEST['parent']) : 0); @@ -49,13 +52,20 @@ class Poke extends \Zotlabs\Web\Controller { logger('poke: verb ' . $verb . ' contact ' . $contact_id, LOGGER_DEBUG); - $r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1", - intval($contact_id), - intval($uid) - ); - + if($contact_id) { + $r = q("SELECT * FROM abook left join xchan on xchan_hash = abook_xchan where abook_id = %d and abook_channel = %d LIMIT 1", + intval($contact_id), + intval($uid) + ); + } + if($xchan) { + $r = q("SELECT * FROM xchan where xchan_hash like ( '%s' ) LIMIT 1", + dbesc($xchan . '%') + ); + } + if(! $r) { - logger('poke: no target ' . $contact_id); + logger('poke: no target.'); return; } @@ -79,7 +89,7 @@ class Poke extends \Zotlabs\Web\Controller { $deny_gid = $r[0]['deny_gid']; } } - else { + elseif($contact_id) { $item_private = ((x($_GET,'private')) ? intval($_GET['private']) : 0); @@ -92,9 +102,11 @@ class Poke extends \Zotlabs\Web\Controller { $arr = array(); + + $arr['item_wall'] = 1; $arr['owner_xchan'] = (($parent_item) ? $parent_item['owner_xchan'] : $channel['channel_hash']); - $arr['parent_mid'] = (($parent_mid) ? $parent_mid : $mid); + $arr['parent_mid'] = (($parent_mid) ? $parent_mid : ''); $arr['title'] = ''; $arr['allow_cid'] = $allow_cid; $arr['allow_gid'] = $allow_gid; diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 46210abb1..28c34425c 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -167,7 +167,7 @@ class Pubstream extends \Zotlabs\Web\Controller { // fake it $mode = ('network'); - $o .= conversation($a,$items,$mode,$update,$page_mode); + $o .= conversation($items,$mode,$update,$page_mode); if(($items) && (! $update)) $o .= alt_pager($a,count($items)); diff --git a/Zotlabs/Module/Register.php b/Zotlabs/Module/Register.php index 1d8944d8e..d4573156c 100644 --- a/Zotlabs/Module/Register.php +++ b/Zotlabs/Module/Register.php @@ -151,7 +151,7 @@ class Register extends \Zotlabs\Web\Controller { $new_channel = false; $next_page = 'new_channel'; - if(get_config('system','auto_channel_create') || get_config('system','server_role') == 'basic') { + if(get_config('system','auto_channel_create')) { $new_channel = auto_channel_create($result['account']['account_id']); if($new_channel['success']) { $channel_id = $new_channel['channel']['channel_id']; @@ -237,14 +237,12 @@ class Register extends \Zotlabs\Web\Controller { $name = array('name', t('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"')); $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/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 role with your privacy requirements.') . ' <a href="help/member/member_guide#Account_Permission_Roles" target="_blank">' . t('Read more about roles') . '</a>',$perm_roles); $tos = array('tos', $label_tos, '', '', array(t('no'),t('yes'))); - $server_role = get_config('system','server_role'); - - $auto_create = (($server_role == 'basic') || (get_config('system','auto_channel_create')) ? true : false); - $default_role = (($server_role == 'basic') ? 'social' : get_config('system','default_permissions_role')); + $auto_create = (get_config('system','auto_channel_create') ? true : false); + $default_role = get_config('system','default_permissions_role'); require_once('include/bbcode.php'); diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php index a78a023ff..2b949ebc7 100644 --- a/Zotlabs/Module/Search.php +++ b/Zotlabs/Module/Search.php @@ -225,7 +225,7 @@ class Search extends \Zotlabs\Web\Controller { else $o .= '<h2>' . sprintf( t('Search results for: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>'; - $o .= conversation($a,$items,'search',$update,'client'); + $o .= conversation($items,'search',$update,'client'); $o .= '</div>'; diff --git a/Zotlabs/Module/Settings/Account.php b/Zotlabs/Module/Settings/Account.php index ec176797d..18890e89f 100644 --- a/Zotlabs/Module/Settings/Account.php +++ b/Zotlabs/Module/Settings/Account.php @@ -16,7 +16,7 @@ class Account { $account = \App::get_account(); if($email != $account['account_email']) { - if(! valid_email($email)) + if(! validate_email($email)) $errs[] = t('Not valid email.'); $adm = trim(get_config('system','admin_email')); if(($adm) && (strcasecmp($email,$adm) == 0)) { diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 12ad25d51..3e6adcf8d 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -489,7 +489,6 @@ class Channel { '$h_prv' => t('Security and Privacy Settings'), '$permissions_set' => $permissions_set, - '$server_role' => \Zotlabs\Lib\System::get_server_role(), '$perms_set_msg' => t('Your permissions are already configured. Click to view/adjust'), '$hide_presence' => array('hide_presence', t('Hide my online presence'),$hide_presence, t('Prevents displaying in your profile that you are online'), $yes_no), diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index d4c31fd4e..e5b54cc5f 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -73,9 +73,6 @@ class Setup extends \Zotlabs\Web\Controller { $phpath = trim($_POST['phpath']); $adminmail = trim($_POST['adminmail']); $siteurl = trim($_POST['siteurl']); - $server_role = trim($_POST['server_role']); - if(! $server_role) - $server_role = 'standard'; // $siteurl should not have a trailing slash @@ -103,9 +100,6 @@ class Setup extends \Zotlabs\Web\Controller { $timezone = trim($_POST['timezone']); $adminmail = trim($_POST['adminmail']); $siteurl = trim($_POST['siteurl']); - $server_role = trim($_POST['server_role']); - if(! $server_role) - $server_role = 'standard'; if($siteurl != z_root()) { $test = z_fetch_url($siteurl."/setup/testrewrite"); @@ -134,7 +128,7 @@ class Setup extends \Zotlabs\Web\Controller { '$dbpass' => $dbpass, '$dbdata' => $dbdata, '$dbtype' => $dbtype, - '$server_role' => $server_role, + '$server_role' => 'pro', '$timezone' => $timezone, '$siteurl' => $siteurl, '$site_id' => random_string(), @@ -324,11 +318,6 @@ class Setup extends \Zotlabs\Web\Controller { $siteurl = trim($_POST['siteurl']); $timezone = ((x($_POST,'timezone')) ? ($_POST['timezone']) : 'America/Los_Angeles'); - $server_roles = [ - 'basic' => t('Basic/Minimal Social Networking'), - 'standard' => t('Standard Configuration (default)'), - 'pro' => t('Professional') - ]; $tpl = get_markup_template('install_settings.tpl'); $o .= replace_macros($tpl, array( @@ -348,8 +337,6 @@ class Setup extends \Zotlabs\Web\Controller { '$siteurl' => array('siteurl', t('Website URL'), z_root(), t('Please use SSL (https) URL if available.')), - '$server_role' => array('server_role', t("Server Configuration/Role"), 'standard','',$server_roles), - '$timezone' => array('timezone', t('Please select a default timezone for your website'), $timezone, '', get_timezones()), '$baseurl' => z_root(), diff --git a/Zotlabs/Module/Share.php b/Zotlabs/Module/Share.php index fcc2486ba..5c4811c59 100644 --- a/Zotlabs/Module/Share.php +++ b/Zotlabs/Module/Share.php @@ -76,7 +76,7 @@ class Share extends \Zotlabs\Web\Controller { $observer = \App::get_observer(); $parsed = $observer['xchan_url']; if($parsed) { - $post_url = $parsed['scheme'] . ':' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '') + $post_url = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '') . '/rpost'; /** diff --git a/Zotlabs/Module/Token.php b/Zotlabs/Module/Token.php new file mode 100644 index 000000000..e0d9d74d7 --- /dev/null +++ b/Zotlabs/Module/Token.php @@ -0,0 +1,40 @@ +<?php + +namespace Zotlabs\Module; + + +class Token extends \Zotlabs\Web\Controller { + + + function get() { + + + // workaround for HTTP-auth in CGI mode + if (x($_SERVER, 'REDIRECT_REMOTE_USER')) { + $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } + } + + if (x($_SERVER, 'HTTP_AUTHORIZATION')) { + $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } + } + + + + + require_once('include/oauth2.php'); + $oauth2_server->handleTokenRequest(\OAuth2\Request::createFromGlobals())->send(); + + killme(); + } + +}
\ No newline at end of file diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index 641e84b70..d59fcdb9f 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -179,11 +179,8 @@ class Webpages extends \Zotlabs\Web\Controller { // so just list titles and an edit link. - /** @TODO - this should be replaced with pagelist_widget */ - $sql_extra = item_permissions_sql($owner); - $r = q("select * from iconfig left join item on iconfig.iid = item.id where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item_type = %d $sql_extra order by item.created desc", @@ -191,12 +188,6 @@ class Webpages extends \Zotlabs\Web\Controller { intval(ITEM_TYPE_WEBPAGE) ); -// $r = q("select * from item_id left join item on item_id.iid = item.id -// where item_id.uid = %d and service = 'WEBPAGE' and item_type = %d $sql_extra order by item.created desc", -// intval($owner), -// intval(ITEM_TYPE_WEBPAGE) -// ); - if(! $r) $x['pagetitle'] = 'home'; diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 2f1fa01b7..85481754f 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -355,6 +355,7 @@ class Wiki extends \Zotlabs\Web\Controller { $html = Zlib\NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))),$wikiURL); } else { + $bb = Zlib\NativeWikiPage::bbcode($content); $x = new ZLib\MarkdownSoap($bb); $md = $x->clean(); diff --git a/Zotlabs/Module/Xrd.php b/Zotlabs/Module/Xrd.php index 7b36576e0..9630e9ab4 100644 --- a/Zotlabs/Module/Xrd.php +++ b/Zotlabs/Module/Xrd.php @@ -9,6 +9,7 @@ class Xrd extends \Zotlabs\Web\Controller { function init() { $uri = urldecode(notags(trim($_GET['uri']))); + $subject = $uri; logger('xrd: ' . $uri,LOGGER_DEBUG); $resource = $uri; @@ -30,13 +31,7 @@ class Xrd extends \Zotlabs\Web\Controller { ); if(! $r) killme(); - - $dspr = replace_macros(get_markup_template('xrd_diaspora.tpl'),array( - '$baseurl' => z_root(), - '$dspr_guid' => $r[0]['channel_guid'] . str_replace('.','',\App::get_hostname()), - '$dspr_key' => base64_encode(pemtorsa($r[0]['channel_pubkey'])) - )); - + $salmon_key = salmon_key($r[0]['channel_pubkey']); header('Access-Control-Allow-Origin: *'); @@ -49,11 +44,11 @@ class Xrd extends \Zotlabs\Web\Controller { if($aliases[$x] === $resource) unset($aliases[$x]); } - - + $o = replace_macros(get_markup_template('xrd_person.tpl'), array( '$nick' => $r[0]['channel_address'], '$accturi' => $resource, + '$subject' => $subject, '$aliases' => $aliases, '$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'], '$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'], @@ -61,12 +56,8 @@ class Xrd extends \Zotlabs\Web\Controller { '$zot_post' => z_root() . '/post/' . $r[0]['channel_address'], '$poco_url' => z_root() . '/poco/' . $r[0]['channel_address'], '$photo' => z_root() . '/photo/profile/l/' . $r[0]['channel_id'], - '$dspr' => $dspr, - // '$salmon' => z_root() . '/salmon/' . $r[0]['channel_address'], - // '$salmen' => z_root() . '/salmon/' . $r[0]['channel_address'] . '/mention', '$modexp' => 'data:application/magic-public-key,' . $salmon_key, '$subscribe' => z_root() . '/follow?url={uri}', - '$bigkey' => salmon_key($r[0]['channel_pubkey']) )); diff --git a/Zotlabs/Storage/Browser.php b/Zotlabs/Storage/Browser.php index 7162161ef..9dc393167 100644 --- a/Zotlabs/Storage/Browser.php +++ b/Zotlabs/Storage/Browser.php @@ -17,6 +17,7 @@ use Sabre\DAV; */ class Browser extends DAV\Browser\Plugin { + public $build_page = false; /** * @see set_writeable() * @see \\Sabre\\DAV\\Auth\\Backend\\BackendInterface @@ -257,7 +258,7 @@ class Browser extends DAV\Browser\Plugin { } } $this->server->httpResponse->setHeader('Content-Security-Policy', "script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"); - construct_page(); + $this->build_page = true; } /** diff --git a/Zotlabs/Widget/Cdav.php b/Zotlabs/Widget/Cdav.php new file mode 100644 index 000000000..1b33668ad --- /dev/null +++ b/Zotlabs/Widget/Cdav.php @@ -0,0 +1,176 @@ +<?php + +namespace Zotlabs\Widget; + + + +class Cdav { + + function widget() { + if(!local_channel()) + return; + + $channel = \App::get_channel(); + $principalUri = 'principals/' . $channel['channel_hash']; + + if(!cdav_principal($principalUri)) + return; + + $pdo = \DBA::$dba->db; + + require_once 'vendor/autoload.php'; + + $o = ''; + + if(argc() == 2 && argv(1) === 'calendar') { + + $caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo); + + $sabrecals = $caldavBackend->getCalendarsForUser($principalUri); + + //TODO: we should probably also check for permission to send stream here + $local_channels = q("SELECT * FROM channel LEFT JOIN abook ON abook_xchan = channel_hash WHERE channel_system = 0 AND channel_removed = 0 AND channel_hash != '%s' AND abook_channel = %d", + dbesc($channel['channel_hash']), + intval($channel['channel_id']) + ); + + $sharee_options .= '<option value="">' . t('Select Channel') . '</option>' . "\r\n"; + foreach($local_channels as $local_channel) { + $sharee_options .= '<option value="' . $local_channel['channel_hash'] . '">' . $local_channel['channel_name'] . '</option>' . "\r\n"; + } + + $access_options = '<option value="3">' . t('Read-write') . '</option>' . "\r\n"; + $access_options .= '<option value="2">' . t('Read-only') . '</option>' . "\r\n"; + + //list calendars + foreach($sabrecals as $sabrecal) { + if($sabrecal['share-access'] == 1) + $access = ''; + if($sabrecal['share-access'] == 2) + $access = 'read'; + if($sabrecal['share-access'] == 3) + $access = 'read-write'; + + $invites = $caldavBackend->getInvites($sabrecal['id']); + + $json_source = '/cdav/calendar/json/' . $sabrecal['id'][0] . '/' . $sabrecal['id'][1]; + + $switch = get_pconfig(local_channel(), 'cdav_calendar', $sabrecal['id'][0]); + + $color = (($sabrecal['{http://apple.com/ns/ical/}calendar-color']) ? $sabrecal['{http://apple.com/ns/ical/}calendar-color'] : '#3a87ad'); + + $editable = (($sabrecal['share-access'] == 2) ? 'false' : 'true'); // false/true must be string since we're passing it to javascript + + $sharees = []; + $share_displayname = []; + foreach($invites as $invite) { + if(strpos($invite->href, 'mailto:') !== false) { + $sharee = channelx_by_hash(substr($invite->href, 7)); + $sharees[] = [ + 'name' => $sharee['channel_name'], + 'access' => (($invite->access == 3) ? ' (RW)' : ' (R)'), + 'hash' => $sharee['channel_hash'] + ]; + } + } + + if(!$access) { + $my_calendars[] = [ + 'ownernick' => $channel['channel_address'], + 'uri' => $sabrecal['uri'], + 'displayname' => $sabrecal['{DAV:}displayname'], + 'calendarid' => $sabrecal['id'][0], + 'instanceid' => $sabrecal['id'][1], + 'json_source' => $json_source, + 'color' => $color, + 'editable' => $editable, + 'switch' => $switch, + 'sharees' => $sharees + ]; + } + else { + $shared_calendars[] = [ + 'ownernick' => $channel['channel_address'], + 'uri' => $sabrecal['uri'], + 'displayname' => $sabrecal['{DAV:}displayname'], + 'calendarid' => $sabrecal['id'][0], + 'instanceid' => $sabrecal['id'][1], + 'json_source' => $json_source, + 'color' => $color, + 'editable' => $editable, + 'switch' => $switch, + 'sharer' => $sabrecal['{urn:ietf:params:xml:ns:caldav}calendar-description'], + 'access' => $access + ]; + } + + if(!$access || $access === 'read-write') { + $writable_calendars[] = [ + 'displayname' => ((!$access) ? $sabrecal['{DAV:}displayname'] : $share_displayname[0]), + 'id' => $sabrecal['id'] + ]; + } + } + + $o .= replace_macros(get_markup_template('cdav_widget_calendar.tpl'), [ + '$my_calendars_label' => t('My Calendars'), + '$my_calendars' => $my_calendars, + '$shared_calendars_label' => t('Shared Calendars'), + '$shared_calendars' => $shared_calendars, + '$sharee_options' => $sharee_options, + '$access_options' => $access_options, + '$share_label' => t('Share this calendar'), + '$share' => t('Share'), + '$edit_label' => t('Calendar name and color'), + '$edit' => t('Edit'), + '$create_label' => t('Create new calendar'), + '$create' => t('Create'), + '$create_placeholder' => t('Calendar Name'), + '$tools_label' => t('Calendar Tools'), + '$import_label' => t('Import calendar'), + '$import_placeholder' => t('Select a calendar to import to'), + '$upload' => t('Upload'), + '$writable_calendars' => $writable_calendars + ]); + + return $o; + + } + + if(argc() >= 2 && argv(1) === 'addressbook') { + + $carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo); + + $sabreabooks = $carddavBackend->getAddressBooksForUser($principalUri); + + //list addressbooks + foreach($sabreabooks as $sabreabook) { + $addressbooks[] = [ + 'ownernick' => $channel['channel_address'], + 'uri' => $sabreabook['uri'], + 'displayname' => $sabreabook['{DAV:}displayname'], + 'id' => $sabreabook['id'] + + ]; + } + + $o .= replace_macros(get_markup_template('cdav_widget_addressbook.tpl'), [ + '$addressbooks_label' => t('Addressbooks'), + '$addressbooks' => $addressbooks, + '$edit_label' => t('Addressbook name'), + '$edit' => t('Edit'), + '$create_label' => t('Create new addressbook'), + '$create_placeholder' => t('Addressbook Name'), + '$create' => t('Create'), + '$tools_label' => t('Addressbook Tools'), + '$import_label' => t('Import addressbook'), + '$import_placeholder' => t('Select an addressbook to import to'), + '$upload' => t('Upload') + ]); + + return $o; + + } + + } +}
\ No newline at end of file diff --git a/Zotlabs/Widget/Conversations.php b/Zotlabs/Widget/Conversations.php index 27e517c02..4fd754f66 100644 --- a/Zotlabs/Widget/Conversations.php +++ b/Zotlabs/Widget/Conversations.php @@ -12,10 +12,6 @@ class Conversations { if(argc() > 1) { switch(argv(1)) { - case 'combined': - $mailbox = 'combined'; - $header = t('Conversations'); - break; case 'inbox': $mailbox = 'inbox'; $header = t('Received Messages'); @@ -58,7 +54,7 @@ class Conversations { 'body' => $rr['body'], 'date' => datetime_convert('UTC',date_default_timezone_get(),$rr['created'], 'c'), 'seen' => $rr['seen'], - 'selected' => ((argv(2)) ? (argv(2) == $rr['id']) : ($r[0]['id'] == $rr['id'])) + 'selected' => ((argc() == 2) ? (intval(argv(1)) == intval($rr['id'])) : ($r[0]['id'] == $rr['id'])) ); } @@ -71,4 +67,6 @@ class Conversations { } return $o; } + } + diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php index 753390c23..c15ad0980 100644 --- a/Zotlabs/Widget/Settings_menu.php +++ b/Zotlabs/Widget/Settings_menu.php @@ -79,11 +79,13 @@ class Settings_menu { 'selected' => '' ); - $tabs[] = array( - 'label' => t('Connected apps'), - 'url' => z_root() . '/settings/oauth', - 'selected' => ((argv(1) === 'oauth') ? 'active' : ''), - ); + if(get_account_techlevel() > 0) { + $tabs[] = array( + 'label' => t('Connected apps'), + 'url' => z_root() . '/settings/oauth', + 'selected' => ((argv(1) === 'oauth') ? 'active' : ''), + ); + } if(get_account_techlevel() > 2) { $tabs[] = array( diff --git a/Zotlabs/Widget/Tasklist.php b/Zotlabs/Widget/Tasklist.php index 6f7a8aaed..3961eecce 100644 --- a/Zotlabs/Widget/Tasklist.php +++ b/Zotlabs/Widget/Tasklist.php @@ -8,8 +8,8 @@ class Tasklist { function widget($arr) { - if (! local_channel()) - return; + if (! local_channel()) + return; $o .= '<script>var tasksShowAll = 0; $(document).ready(function() { tasksFetch(); $("#tasklist-new-form").submit(function(event) { event.preventDefault(); $.post( "tasks/new", $("#tasklist-new-form").serialize(), function(data) { tasksFetch(); $("#tasklist-new-summary").val(""); } ); return false; } )});</script>'; $o .= '<script>function taskComplete(id) { $.post("tasks/complete/"+id, function(data) { tasksFetch();}); } |