diff options
Diffstat (limited to 'Zotlabs')
123 files changed, 3609 insertions, 902 deletions
diff --git a/Zotlabs/Access/AccessList.php b/Zotlabs/Access/AccessList.php index b073f9d3c..6471b0b1d 100644 --- a/Zotlabs/Access/AccessList.php +++ b/Zotlabs/Access/AccessList.php @@ -2,21 +2,55 @@ namespace Zotlabs\Access; - +/** + * @brief AccessList class. + * + * A class to hold an AccessList object with allowed and denied contacts and + * groups. + */ class AccessList { - + /** + * @brief Allow contacts + * @var string + */ private $allow_cid; + /** + * @brief Allow groups + * @var string + */ private $allow_gid; + /** + * @brief Deny contacts + * @var string + */ private $deny_cid; + /** + * @brief Deny groups + * @var string + */ private $deny_gid; + /** + * @brief Indicates if we are using the default constructor values or + * values that have been set explicitly. + * @var boolean + */ + private $explicit; - /* indicates if we are using the default constructor values or values that have been set explicitly. */ - - private $explicit; + /** + * @brief Constructor for AccessList class. + * + * @note The array to pass to the constructor is different from the array + * that you provide to the set() or set_from_array() functions. + * + * @param array $channel A channel array, where these entries are evaluated: + * * \e string \b channel_allow_cid => string of allowed cids + * * \e string \b channel_allow_gid => string of allowed gids + * * \e string \b channel_deny_cid => string of denied cids + * * \e string \b channel_deny_gid => string of denied gids + */ function __construct($channel) { - - if($channel) { + if($channel) { $this->allow_cid = $channel['channel_allow_cid']; $this->allow_gid = $channel['channel_allow_gid']; $this->deny_cid = $channel['channel_deny_cid']; @@ -32,61 +66,95 @@ class AccessList { $this->explicit = false; } + /** + * @brief Get if we are using the default constructor values + * or values that have been set explicitly. + * + * @return boolean + */ function get_explicit() { return $this->explicit; } /** - * Set AccessList from strings such as those in already - * existing stored data items + * @brief Set access list from strings such as those in already + * existing stored data items. + * + * @note The array to pass to this set function is different from the array + * that you provide to the constructor or set_from_array(). + * + * @param array $arr + * * \e string \b allow_cid => string of allowed cids + * * \e string \b allow_gid => string of allowed gids + * * \e string \b deny_cid => string of denied cids + * * \e string \b deny_gid => string of denied gids + * @param boolean $explicit (optional) default true */ - - function set($arr,$explicit = true) { + function set($arr, $explicit = true) { $this->allow_cid = $arr['allow_cid']; $this->allow_gid = $arr['allow_gid']; $this->deny_cid = $arr['deny_cid']; $this->deny_gid = $arr['deny_gid']; - $this->explicit = $explicit; + $this->explicit = $explicit; } /** - * return an array consisting of the current - * access list components where the elements - * are directly storable. + * @brief Return an array consisting of the current access list components + * where the elements are directly storable. + * + * @return Associative array with: + * * \e string \b allow_cid => string of allowed cids + * * \e string \b allow_gid => string of allowed gids + * * \e string \b deny_cid => string of denied cids + * * \e string \b deny_gid => string of denied gids */ - function get() { - return array( + return [ 'allow_cid' => $this->allow_cid, 'allow_gid' => $this->allow_gid, 'deny_cid' => $this->deny_cid, 'deny_gid' => $this->deny_gid, - ); + ]; } /** - * Set AccessList from arrays, such as those provided by - * acl_selector(). For convenience, a string (or non-array) input is - * assumed to be a comma-separated list and auto-converted into an array. - */ - - function set_from_array($arr,$explicit = true) { - $this->allow_cid = perms2str((is_array($arr['contact_allow'])) - ? $arr['contact_allow'] : explode(',',$arr['contact_allow'])); + * @brief Set access list components from arrays, such as those provided by + * acl_selector(). + * + * For convenience, a string (or non-array) input is assumed to be a + * comma-separated list and auto-converted into an array. + * + * @note The array to pass to this set function is different from the array + * that you provide to the constructor or set(). + * + * @param array $arr An associative array with: + * * \e array|string \b contact_allow => array with cids or comma-seperated string + * * \e array|string \b group_allow => array with gids or comma-seperated string + * * \e array|string \b contact_deny => array with cids or comma-seperated string + * * \e array|string \b group_deny => array with gids or comma-seperated string + * @param boolean $explicit (optional) default true + */ + function set_from_array($arr, $explicit = true) { + $this->allow_cid = perms2str((is_array($arr['contact_allow'])) + ? $arr['contact_allow'] : explode(',', $arr['contact_allow'])); $this->allow_gid = perms2str((is_array($arr['group_allow'])) - ? $arr['group_allow'] : explode(',',$arr['group_allow'])); + ? $arr['group_allow'] : explode(',', $arr['group_allow'])); $this->deny_cid = perms2str((is_array($arr['contact_deny'])) - ? $arr['contact_deny'] : explode(',',$arr['contact_deny'])); + ? $arr['contact_deny'] : explode(',', $arr['contact_deny'])); $this->deny_gid = perms2str((is_array($arr['group_deny'])) - ? $arr['group_deny'] : explode(',',$arr['group_deny'])); + ? $arr['group_deny'] : explode(',', $arr['group_deny'])); $this->explicit = $explicit; } + /** + * @brief Returns true if any access lists component is set. + * + * @return boolean Return true if any of allow_* deny_* values is set. + */ function is_private() { return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false); } } - diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php index 350dda7a0..c84708ba4 100644 --- a/Zotlabs/Daemon/Cron.php +++ b/Zotlabs/Daemon/Cron.php @@ -121,6 +121,9 @@ class Cron { } } + require_once('include/attach.php'); + attach_upgrade(); + $abandon_days = intval(get_config('system','account_abandon_days')); if($abandon_days < 1) $abandon_days = 0; diff --git a/Zotlabs/Daemon/Cron_daily.php b/Zotlabs/Daemon/Cron_daily.php index 0f0001890..038790572 100644 --- a/Zotlabs/Daemon/Cron_daily.php +++ b/Zotlabs/Daemon/Cron_daily.php @@ -38,6 +38,13 @@ class Cron_daily { db_utcnow(), db_quoteinterval('30 DAY') ); + // expire any unread notifications over a year old + + q("delete from notify where seen = 0 and created < %s - INTERVAL %s", + db_utcnow(), db_quoteinterval('1 YEAR') + ); + + //update statistics in config require_once('include/statistics_fns.php'); update_channels_total_stat(); diff --git a/Zotlabs/Daemon/Notifier.php b/Zotlabs/Daemon/Notifier.php index 63ced4f56..3afe1a5dc 100644 --- a/Zotlabs/Daemon/Notifier.php +++ b/Zotlabs/Daemon/Notifier.php @@ -5,6 +5,11 @@ namespace Zotlabs\Daemon; require_once('include/queue_fn.php'); require_once('include/html2plain.php'); require_once('include/conversation.php'); +require_once('include/zot.php'); +require_once('include/items.php'); +require_once('include/bbcode.php'); + + /* * This file was at one time responsible for doing all deliveries, but this caused @@ -68,13 +73,6 @@ require_once('include/conversation.php'); */ -require_once('include/zot.php'); -require_once('include/queue_fn.php'); -require_once('include/datetime.php'); -require_once('include/items.php'); -require_once('include/bbcode.php'); -require_once('include/channel.php'); - class Notifier { @@ -98,16 +96,6 @@ class Notifier { $deliveries = array(); - $dead_hubs = array(); - - $dh = q("select site_url from site where site_dead = 1"); - if($dh) { - foreach($dh as $dead) { - $dead_hubs[] = $dead['site_url']; - } - } - - $request = false; $mail = false; $top_level = false; @@ -489,10 +477,10 @@ class Notifier { // Now we have collected recipients (except for external mentions, FIXME) - // Let's reduce this to a set of hubs. + // Let's reduce this to a set of hubs; checking that the site is not dead. $r = q("select hubloc.*, site.site_crypto from hubloc left join site on site_url = hubloc_url where hubloc_hash in (" . implode(',',$recipients) . ") - and hubloc_error = 0 and hubloc_deleted = 0" + and hubloc_error = 0 and hubloc_deleted = 0 and ( site_dead = 0 OR site_dead is null ) " ); @@ -506,23 +494,31 @@ class Notifier { /** - * 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. + * 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. * For other networks which don't have or require sitekeys, we'll have to use the URL */ - $hublist = array(); // this provides an easily printable list for the logs - $dhubs = array(); // delivery hubs where we store our resulting unique array - $keys = array(); // array of keys to check uniquness for zot hubs - $urls = array(); // array of urls to check uniqueness of hubs from other networks - + $hublist = []; // this provides an easily printable list for the logs + $dhubs = []; // delivery hubs where we store our resulting unique array + $keys = []; // array of keys to check uniquness for zot hubs + $urls = []; // array of urls to check uniqueness of hubs from other networks + $hub_env = []; // per-hub envelope so we don't broadcast the entire envelope to all foreach($hubs as $hub) { - if(in_array($hub['hubloc_url'],$dead_hubs)) { - logger('skipping dead hub: ' . $hub['hubloc_url'], LOGGER_DEBUG, LOG_INFO); - continue; + + if($env_recips) { + foreach($env_recips as $er) { + if($hub['hubloc_hash'] === $er['hash']) { + if(! array_key_exists($hub['hubloc_host'] . $hub['hubloc_sitekey'], $hub_env)) { + $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] = []; + } + $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']][] = $er; + } + } } + if($hub['hubloc_network'] == 'zot') { if(! in_array($hub['hubloc_sitekey'],$keys)) { @@ -603,7 +599,8 @@ class Notifier { $packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null)); } elseif($packet_type === 'request') { - $packet = zot_build_packet($channel,$packet_type,$env_recips,$hub['hubloc_sitekey'],$hub['site_crypto'], + $env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : ''); + $packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'], $hash, array('message_id' => $request_message_id) ); } @@ -618,7 +615,8 @@ class Notifier { )); } else { - $packet = zot_build_packet($channel,'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash); + $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'], diff --git a/Zotlabs/Daemon/Onepoll.php b/Zotlabs/Daemon/Onepoll.php index 33b244dc5..920916828 100644 --- a/Zotlabs/Daemon/Onepoll.php +++ b/Zotlabs/Daemon/Onepoll.php @@ -118,13 +118,29 @@ class Onepoll { if($fetch_feed) { - $feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']); - $feedurl .= '?f=&mindate=' . urlencode($last_update); + if(strpos($contact['xchan_connurl'],z_root()) === 0) { + // local channel - save a network fetch + $c = channelx_by_hash($contact['xchan_hash']); + if($c) { + $x = [ + 'success' => true, + 'body' => json_encode( [ + 'success' => true, + 'messages' => zot_feed($c['channel_id'], $importer['xchan_hash'], [ 'mindate' => $last_update ]) + ]) + ]; + } + } + else { + // remote fetch - $x = z_fetch_url($feedurl); + $feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']); + $feedurl .= '?f=&mindate=' . urlencode($last_update) . '&zid=' . $importer['channel_address'] . '@' . \App::get_hostname(); + $recurse = 0; + $x = z_fetch_url($feedurl, false, $recurse, [ 'session' => true ]); + } logger('feed_update: ' . print_r($x,true), LOGGER_DATA); - } if(($x) && ($x['success'])) { diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index 0ca2f7a99..2ace361ca 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -34,7 +34,7 @@ class Apps { if($files) { foreach($files as $f) { $path = explode('/',$f); - $plugin = $path[1]; + $plugin = trim($path[1]); if(plugin_is_installed($plugin)) { $x = self::parse_app_description($f,$translate); if($x) { @@ -219,7 +219,7 @@ class Apps { 'Suggest Channels' => t('Suggest Channels'), 'Login' => t('Login'), 'Channel Manager' => t('Channel Manager'), - 'Grid' => t('Grid'), + 'Grid' => t('Activity'), 'Settings' => t('Settings'), 'Files' => t('Files'), 'Webpages' => t('Webpages'), @@ -245,9 +245,19 @@ class Apps { 'Profile Photo' => t('Profile Photo') ); - if(array_key_exists($arr['name'],$apps)) { - $arr['name'] = $apps[$arr['name']]; + if(array_key_exists('name',$arr)) { + if(array_key_exists($arr['name'],$apps)) { + $arr['name'] = $apps[$arr['name']]; + } + } + else { + for($x = 0; $x < count($arr); $x++) { + if(array_key_exists($arr[$x]['name'],$apps)) { + $arr[$x]['name'] = $apps[$arr[$x]['name']]; + } + } } + } @@ -275,7 +285,7 @@ class Apps { self::translate_system_apps($papp); - if(($papp['plugin']) && (! plugin_is_installed($papp['plugin']))) + if(trim($papp['plugin']) && (! plugin_is_installed(trim($papp['plugin'])))) return ''; $papp['papp'] = self::papp_encode($papp); @@ -565,7 +575,7 @@ class Apps { $darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : ''); $darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : ''); $darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : ''); - $darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags($arr['plugin']) : ''); + $darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags(trim($arr['plugin'])) : ''); $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : ''); $darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0); $darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0); @@ -643,7 +653,7 @@ class Apps { $darray['app_addr'] = ((x($arr,'addr')) ? escape_tags($arr['addr']) : ''); $darray['app_price'] = ((x($arr,'price')) ? escape_tags($arr['price']) : ''); $darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : ''); - $darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags($arr['plugin']) : ''); + $darray['app_plugin'] = ((x($arr,'plugin')) ? escape_tags(trim($arr['plugin'])) : ''); $darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : ''); $darray['app_system'] = ((x($arr,'system')) ? intval($arr['system']) : 0); $darray['app_deleted'] = ((x($arr,'deleted')) ? intval($arr['deleted']) : 0); @@ -753,7 +763,7 @@ class Apps { $ret['system'] = $app['app_system']; if($app['app_plugin']) - $ret['plugin'] = $app['app_plugin']; + $ret['plugin'] = trim($app['app_plugin']); if($app['app_deleted']) $ret['deleted'] = $app['app_deleted']; diff --git a/Zotlabs/Lib/DB_Upgrade.php b/Zotlabs/Lib/DB_Upgrade.php new file mode 100644 index 000000000..bb72e7a05 --- /dev/null +++ b/Zotlabs/Lib/DB_Upgrade.php @@ -0,0 +1,119 @@ +<?php + +namespace Zotlabs\Lib; + + +class DB_Upgrade { + + public $config_name = ''; + public $func_prefix = ''; + + function __construct($db_revision) { + + $update_file = 'install/' . PLATFORM_NAME . '/update.php'; + if(! file_exists($update_file)) { + $update_file = 'install/update.php'; + $this->config_name = 'db_version'; + $this->func_prefix = 'update_r'; + } + else { + $this->config_name = PLATFORM_NAME . '_db_version'; + $this->func_prefix = PLATFORM_NAME . '_update_'; + } + + $build = get_config('system', $this->config_name, 0); + if(! intval($build)) + $build = set_config('system', $this->config_name, $db_revision); + + if($build == $db_revision) { + // Nothing to be done. + return; + } + else { + $stored = intval($build); + if(! $stored) { + logger('Critical: check_config unable to determine database schema version'); + return; + } + + $current = intval($db_revision); + + if(($stored < $current) && file_exists($update_file)) { + + Config::Load('database'); + + // We're reporting a different version than what is currently installed. + // Run any existing update scripts to bring the database up to current. + + require_once($update_file); + + // make sure that boot.php and update.php are the same release, we might be + // updating from git right this very second and the correct version of the update.php + // file may not be here yet. This can happen on a very busy site. + + if($db_revision == UPDATE_VERSION) { + for($x = $stored; $x < $current; $x ++) { + $func = $this->func_prefix . $x; + if(function_exists($func)) { + // There could be a lot of processes running or about to run. + // We want exactly one process to run the update command. + // So store the fact that we're taking responsibility + // after first checking to see if somebody else already has. + + // If the update fails or times-out completely you may need to + // delete the config entry to try again. + + if(get_config('database', $func)) + break; + set_config('database',$func, '1'); + // call the specific update + + $retval = $func(); + if($retval) { + + // Prevent sending hundreds of thousands of emails by creating + // a lockfile. + + $lockfile = 'store/[data]/mailsent'; + + if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 86400))) + return; + @unlink($lockfile); + //send the administrator an e-mail + file_put_contents($lockfile, $x); + + $r = q("select account_language from account where account_email = '%s' limit 1", + dbesc(\App::$config['system']['admin_email']) + ); + push_lang(($r) ? $r[0]['account_language'] : 'en'); + + z_mail( + [ + 'toEmail' => \App::$config['system']['admin_email'], + 'messageSubject' => sprintf( t('Update Error at %s'), z_root()), + 'textVersion' => replace_macros(get_intltext_template('update_fail_eml.tpl'), + [ + '$sitename' => \App::$config['system']['sitename'], + '$siteurl' => z_root(), + '$update' => $x, + '$error' => sprintf( t('Update %s failed. See error logs.'), $x) + ] + ) + ] + ); + + //try the logger + logger('CRITICAL: Update Failed: ' . $x); + pop_lang(); + } + else { + set_config('database',$func, 'success'); + } + } + } + set_config('system', $this->config_name, $db_revision); + } + } + } + } +}
\ No newline at end of file diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php index 257687567..a10675a87 100644 --- a/Zotlabs/Lib/Enotify.php +++ b/Zotlabs/Lib/Enotify.php @@ -67,7 +67,7 @@ class Enotify { $sender_name = $product; $hostname = \App::get_hostname(); if(strpos($hostname,':')) - $hostname = substr($hostname,0,strpos($hostname,':')); + $hostname = substr($hostname,0,strpos($hostname,':')); // Do not translate 'noreply' as it must be a legal 7-bit email address @@ -77,7 +77,7 @@ class Enotify { $sender_email = get_config('system','from_email'); if(! $sender_email) - $sender_email = 'Administrator' . '@' . \App::get_hostname(); + $sender_email = 'Administrator' . '@' . $hostname; $sender_name = get_config('system','from_email_name'); if(! $sender_name) @@ -495,13 +495,14 @@ class Enotify { } } - $r = q("insert into notify (hash,xname,url,photo,created,aid,uid,link,parent,seen,ntype,verb,otype) - values('%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')", + $r = q("insert into notify (hash,xname,url,photo,created,msg,aid,uid,link,parent,seen,ntype,verb,otype) + values('%s','%s','%s','%s','%s','%s',%d,%d,'%s','%s',%d,%d,'%s','%s')", dbesc($datarray['hash']), dbesc($datarray['xname']), dbesc($datarray['url']), dbesc($datarray['photo']), dbesc($datarray['created']), + dbesc(''), // will fill this in below after the record is created intval($datarray['aid']), intval($datarray['uid']), dbesc($datarray['link']), diff --git a/Zotlabs/Lib/MarkdownSoap.php b/Zotlabs/Lib/MarkdownSoap.php new file mode 100644 index 000000000..534ad819f --- /dev/null +++ b/Zotlabs/Lib/MarkdownSoap.php @@ -0,0 +1,103 @@ +<?php + +namespace Zotlabs\Lib; + +/** + * MarkdownSoap + * Purify Markdown for storage + * $x = new MarkdownSoap($string_to_be_cleansed); + * $text = $x->clean(); + * + * What this does: + * 1. extracts code blocks and privately escapes them from processing + * 2. Run html purifier on the content + * 3. put back the code blocks + * 4. run htmlspecialchars on the entire content for safe storage + * + * At render time: + * $markdown = \Zotlabs\Lib\MarkdownSoap::unescape($text); + * $html = \Michelf\MarkdownExtra::DefaultTransform($markdown); + */ + + + +class MarkdownSoap { + + private $token; + + private $str; + + function __construct($s) { + $this->str = $s; + $this->token = random_string(20); + } + + + function clean() { + + $x = $this->extract_code($this->str); + + $x = $this->purify($x); + + $x = $this->putback_code($x); + + $x = $this->escape($x); + + return $x; + } + + function extract_code($s) { + + $text = preg_replace_callback('{ + (?:\n\n|\A\n?) + ( # $1 = the code block -- one or more lines, starting with a space/tab + (?> + [ ]{'.'4'.'} # Lines must start with a tab or a tab-width of spaces + .*\n+ + )+ + ) + ((?=^[ ]{0,'.'4'.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc + }xm', + [ $this , 'encode_code' ], $s); + + return $text; + } + + function encode_code($matches) { + return $this->token . ';' . base64_encode($matches[0]) . ';' ; + } + + function decode_code($matches) { + return base64_decode($matches[1]); + } + + function putback_code($s) { + $text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm',[ $this, 'decode_code' ], $s); + return $text; + } + + function purify($s) { + $s = $this->protect_autolinks($s); + $s = purify_html($s); + $s = $this->unprotect_autolinks($s); + return $s; + } + + function protect_autolinks($s) { + $s = preg_replace('/\<(https?\:\/\/)(.*?)\>/','[$1$2]($1$2)',$s); + return $s; + } + + function unprotect_autolinks($s) { + return $s; + + } + + function escape($s) { + return htmlspecialchars($s,ENT_QUOTES); + } + + static public function unescape($s) { + return htmlspecialchars_decode($s,ENT_QUOTES); + } +} diff --git a/Zotlabs/Lib/NativeWiki.php b/Zotlabs/Lib/NativeWiki.php index 7786ec25a..4301feaa0 100644 --- a/Zotlabs/Lib/NativeWiki.php +++ b/Zotlabs/Lib/NativeWiki.php @@ -101,11 +101,11 @@ class NativeWiki { static public function sync_a_wiki_item($uid,$id,$resource_id) { - $r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = %d )) ", + $r = q("SELECT * from item WHERE uid = %d AND ( id = %d OR ( resource_type = '%s' and resource_id = '%s' )) ", intval($uid), intval($id), dbesc(NWIKI_ITEM_RESOURCE_TYPE), - intval($resource_id) + dbesc($resource_id) ); if($r) { xchan_query($r); diff --git a/Zotlabs/Lib/NativeWikiPage.php b/Zotlabs/Lib/NativeWikiPage.php index 4086a023e..ed3df436c 100644 --- a/Zotlabs/Lib/NativeWikiPage.php +++ b/Zotlabs/Lib/NativeWikiPage.php @@ -21,12 +21,23 @@ class NativeWikiPage { $sql_extra = item_permissions_sql($channel_id,$observer_hash); $r = q("select * from item where resource_type = 'nwikipage' and resource_id = '%s' and uid = %d and item_deleted = 0 - $sql_extra group by mid", + $sql_extra order by created asc", dbesc($resource_id), intval($channel_id) ); if($r) { - $items = fetch_post_tags($r,true); + $x = []; + $y = []; + + foreach($r as $rv) { + if(! in_array($rv['mid'],$x)) { + $y[] = $rv; + $x[] = $rv['mid']; + } + } + + $items = fetch_post_tags($y,true); + foreach($items as $page_item) { $title = get_iconfig($page_item['id'],'nwikipage','pagetitle',t('(No Title)')); if(urldecode($title) !== 'Home') { @@ -156,7 +167,7 @@ class NativeWikiPage { $content = $item['body']; return [ - 'content' => json_encode($content), + 'content' => $content, 'mimeType' => $w['mimeType'], 'message' => '', 'success' => true @@ -307,48 +318,22 @@ class NativeWikiPage { return null; } - - - static public function prepare_content($s) { - - $text = preg_replace_callback('{ - (?:\n\n|\A\n?) - ( # $1 = the code block -- one or more lines, starting with a space/tab - (?> - [ ]{'.'4'.'} # Lines must start with a tab or a tab-width of spaces - .*\n+ - )+ - ) - ((?=^[ ]{0,'.'4'.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc - }xm', - 'self::nwiki_prepare_content_callback', $s); - - return $text; - } - - static public function nwiki_prepare_content_callback($matches) { - $codeblock = $matches[1]; - - $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES, UTF8, false); - return "\n\n" . $codeblock ; - } - - - static public function save_page($arr) { - $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : ''); - $content = ((array_key_exists('content',$arr)) ? purify_html(Zlib\NativeWikiPage::prepare_content($arr['content'])) : ''); - $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : ''); + $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : ''); + $content = ((array_key_exists('content',$arr)) ? $arr['content'] : ''); + $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : ''); $observer_hash = ((array_key_exists('observer_hash',$arr)) ? $arr['observer_hash'] : ''); $channel_id = ((array_key_exists('channel_id',$arr)) ? $arr['channel_id'] : 0); - $revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : 0); + $revision = ((array_key_exists('revision',$arr)) ? $arr['revision'] : 0); $w = Zlib\NativeWiki::get_wiki($channel_id, $observer_hash, $resource_id); if (!$w['wiki']) { return array('message' => t('Error reading wiki'), 'success' => false); } + + $mimetype = $w['mimeType']; // fetch the most recently saved revision. @@ -367,6 +352,7 @@ class NativeWikiPage { $item['author_xchan'] = $observer_hash; $item['revision'] = (($arr['revision']) ? intval($arr['revision']) + 1 : intval($item['revision']) + 1); $item['edited'] = datetime_convert(); + $item['mimetype'] = $mimetype; if($item['iconfig'] && is_array($item['iconfig']) && count($item['iconfig'])) { for($x = 0; $x < count($item['iconfig']); $x ++) { @@ -534,6 +520,29 @@ class NativeWikiPage { } return $s; } + + static public function render_page_history($arr) { + + $pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : ''); + $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : ''); + + $pageHistory = self::page_history([ + 'channel_id' => \App::$profile_uid, + 'observer_hash' => get_observer_hash(), + 'resource_id' => $resource_id, + 'pageUrlName' => $pageUrlName + ]); + + return replace_macros(get_markup_template('nwiki_page_history.tpl'), array( + '$pageHistory' => $pageHistory['history'], + '$permsWrite' => $arr['permsWrite'], + '$name_lbl' => t('Name'), + '$msg_label' => t('Message','wiki_history') + )); + + } + + /** * Replace the instances of the string [toc] with a list element that will be populated by diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 07b782309..5910ea672 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -82,7 +82,8 @@ class ThreadItem { $dropping = false; $star = false; $isstarred = "unstarred fa-star-o"; - $indent = ''; + $is_comment = false; + $is_item = false; $osparkle = ''; $total_children = $this->count_descendants(); $unseen_comments = (($item['real_uid']) ? 0 : $this->count_unseen_descendants()); @@ -183,7 +184,7 @@ class ThreadItem { $like_list = ((x($conv_responses['like'],$item['mid'])) ? $conv_responses['like'][$item['mid'] . '-l'] : ''); if (count($like_list) > MAX_LIKERS) { $like_list_part = array_slice($like_list, 0, MAX_LIKERS); - array_push($like_list_part, '<a href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>'); + array_push($like_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#likeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>'); } else { $like_list_part = ''; } @@ -195,7 +196,7 @@ class ThreadItem { $dislike_button_label = tt('Dislike','Dislikes',$dislike_count,'noun'); if (count($dislike_list) > MAX_LIKERS) { $dislike_list_part = array_slice($dislike_list, 0, MAX_LIKERS); - array_push($dislike_list_part, '<a href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>'); + array_push($dislike_list_part, '<a class="dropdown-item" href="#" data-toggle="modal" data-target="#dislikeModal-' . $this->get_id() . '"><b>' . t('View all') . '</b></a>'); } else { $dislike_list_part = ''; } @@ -232,7 +233,7 @@ class ThreadItem { } } else { - $indent = 'comment'; + $is_comment = true; } @@ -276,13 +277,13 @@ class ThreadItem { $keep_reports = intval(get_config('system','expire_delivery_reports')); if($keep_reports === 0) - $keep_reports = 30; + $keep_reports = 10; if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) $dreport = t('Delivery Report'); if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0) - $indent .= ' shiny'; + $is_new = true; localize_item($item); @@ -337,7 +338,6 @@ class ThreadItem { 'profile_url' => $profile_link, 'thread_action_menu' => thread_action_menu($item,$conv->get_mode()), 'thread_author_menu' => thread_author_menu($item,$conv->get_mode()), - 'item_photo_menu' => item_photo_menu($item), 'dreport' => $dreport, 'name' => $profile_name, 'thumb' => $profile_avatar, @@ -361,7 +361,8 @@ class ThreadItem { 'attend_title' => t('Attendance Options'), 'vote_label' => t('Vote'), 'vote_title' => t('Voting Options'), - 'indent' => $indent, + 'is_comment' => $is_comment, + 'is_new' => $is_new, 'owner_url' => $this->get_owner_url(), 'owner_photo' => $this->get_owner_photo(), 'owner_name' => $this->get_owner_name(), @@ -407,7 +408,7 @@ class ThreadItem { 'showlike' => $showlike, 'showdislike' => $showdislike, 'comment' => $this->get_comment_box($indent), - 'previewing' => ($conv->is_preview() ? ' preview ' : ''), + 'previewing' => ($conv->is_preview() ? true : false ), 'wait' => t('Please wait'), 'submid' => str_replace(['+','='], ['',''], base64_encode(substr($item['mid'],0,32))), 'thread_level' => $thread_level diff --git a/Zotlabs/Module/Admin/Plugins.php b/Zotlabs/Module/Admin/Plugins.php index 527e96496..feb29e9d6 100644 --- a/Zotlabs/Module/Admin/Plugins.php +++ b/Zotlabs/Module/Admin/Plugins.php @@ -3,10 +3,14 @@ namespace Zotlabs\Module\Admin; use \Zotlabs\Storage\GitRepo as GitRepo; +use \Michelf\MarkdownExtra; class Plugins { - + /** + * @brief + * + */ function post() { if(argc() > 2 && is_file("addon/" . argv(2) . "/" . argv(2) . ".php")) { @@ -15,16 +19,15 @@ class Plugins { $func = argv(2) . '_plugin_admin_post'; $func($a); } - - goaway(z_root() . '/admin/plugins/' . argv(2) ); + goaway(z_root() . '/admin/plugins/' . argv(2) ); } elseif(argc() > 2) { switch(argv(2)) { case 'updaterepo': if (array_key_exists('repoName', $_REQUEST)) { $repoName = $_REQUEST['repoName']; - } + } else { json_return_and_die(array('message' => 'No repo name provided.', 'success' => false)); } @@ -101,16 +104,15 @@ class Plugins { logger('Repo directory not writable to web server: ' . $repoDir); json_return_and_die(array('message' => 'Repo directory not writable to web server.', 'success' => false)); } - // TODO: remove directory and unlink /addon/files + /// @TODO remove directory and unlink /addon/files if (rrmdir($repoDir)) { json_return_and_die(array('message' => 'Repo deleted.', 'success' => true)); } else { json_return_and_die(array('message' => 'Error deleting addon repo.', 'success' => false)); } case 'installrepo': - require_once('library/markdown.php'); if (array_key_exists('repoURL', $_REQUEST)) { - require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies + require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies $repoURL = $_REQUEST['repoURL']; $extendDir = 'store/[data]/git/sys/extend'; $addonDir = $extendDir . '/addon'; @@ -170,9 +172,8 @@ class Plugins { json_return_and_die(array('repo' => $repo, 'message' => '', 'success' => true)); } case 'addrepo': - require_once('library/markdown.php'); if (array_key_exists('repoURL', $_REQUEST)) { - require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies + require_once('library/PHPGit.autoload.php'); // Load PHPGit dependencies $repoURL = $_REQUEST['repoURL']; $extendDir = 'store/[data]/git/sys/extend'; $addonDir = $extendDir . '/addon'; @@ -225,7 +226,7 @@ class Plugins { $repo['readme'] = $repo['manifest'] = null; foreach ($git->git->tree('master') as $object) { if ($object['type'] == 'blob' && (strtolower($object['file']) === 'readme.md' || strtolower($object['file']) === 'readme')) { - $repo['readme'] = Markdown($git->git->cat->blob($object['hash'])); + $repo['readme'] = MarkdownExtra::defaultTransform($git->git->cat->blob($object['hash'])); } else if ($object['type'] == 'blob' && strtolower($object['file']) === 'manifest.json') { $repo['manifest'] = $git->git->cat->blob($object['hash']); } @@ -241,7 +242,11 @@ class Plugins { } } - + /** + * @brief Plugins admin page. + * + * @return string with parsed HTML + */ function get() { /* @@ -254,13 +259,13 @@ class Plugins { notice( t("Item not found.") ); return ''; } - + $enabled = in_array($plugin,\App::$plugins); $info = get_plugin_info($plugin); $x = check_plugin_versions($info); - + // disable plugins which are installed but incompatible versions - + if($enabled && ! $x) { $enabled = false; $idz = array_search($plugin, \App::$plugins); @@ -271,7 +276,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'); $pinstalled = false; @@ -297,9 +302,9 @@ class Plugins { } goaway(z_root() . '/admin/plugins' ); } + // display plugin details - require_once('library/markdown.php'); - + if (in_array($plugin, \App::$plugins)){ $status = 'on'; $action = t('Disable'); @@ -307,21 +312,21 @@ class Plugins { $status = 'off'; $action = t('Enable'); } - + $readme = null; if (is_file("addon/$plugin/README.md")){ $readme = file_get_contents("addon/$plugin/README.md"); - $readme = Markdown($readme); + $readme = MarkdownExtra::defaultTransform($readme); } else if (is_file("addon/$plugin/README")){ $readme = "<pre>". file_get_contents("addon/$plugin/README") ."</pre>"; } - + $admin_form = ''; - + $r = q("select * from addon where plugin_admin = 1 and aname = '%s' limit 1", dbesc($plugin) ); - + if($r) { @require_once("addon/$plugin/$plugin.php"); if(function_exists($plugin.'_plugin_admin')) { @@ -329,8 +334,8 @@ class Plugins { $func($a, $admin_form); } } - - + + $t = get_markup_template('admin_plugins_details.tpl'); return replace_macros($t, array( '$title' => t('Administration'), @@ -338,7 +343,7 @@ class Plugins { '$toggle' => t('Toggle'), '$settings' => t('Settings'), '$baseurl' => z_root(), - + '$plugin' => $plugin, '$status' => $status, '$action' => $action, @@ -351,17 +356,17 @@ class Plugins { '$str_serverroles' => t('Compatible Server Roles: '), '$str_requires' => t('Requires: '), '$disabled' => t('Disabled - version incompatibility'), - + '$admin_form' => $admin_form, '$function' => 'plugins', '$screenshot' => '', '$readme' => $readme, - + '$form_security_token' => get_form_security_token('admin_plugins'), )); } - - + + /* * List plugins */ @@ -374,9 +379,9 @@ class Plugins { $info = get_plugin_info($id); $enabled = in_array($id,\App::$plugins); $x = check_plugin_versions($info); - + // disable plugins which are installed but incompatible versions - + if($enabled && ! $x) { $enabled = false; $idz = array_search($id, \App::$plugins); @@ -387,19 +392,19 @@ class Plugins { } } $info['disabled'] = 1-intval($x); - + $plugins[] = array( $id, (($enabled)?"on":"off") , $info); } } } - + usort($plugins,'self::plugin_sort'); $allowManageRepos = false; if(is_writable('extend/addon') && is_writable('store/[data]')) { $allowManageRepos = true; - } - + } + $admin_plugins_add_repo_form= replace_macros( get_markup_template('admin_plugins_addrepo.tpl'), array( '$post' => 'admin/plugins/addrepo', @@ -418,14 +423,14 @@ class Plugins { '$cancel' => t('Cancel') ) ); - + $reponames = $this->listAddonRepos(); $addonrepos = []; foreach($reponames as $repo) { $addonrepos[] = array('name' => $repo, 'description' => ''); - // TODO: Parse repo info to provide more information about repos + /// @TODO Parse repo info to provide more information about repos } - + $t = get_markup_template('admin_plugins.tpl'); return replace_macros($t, array( '$title' => t('Administration'), @@ -471,5 +476,4 @@ class Plugins { return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name']))); } - }
\ No newline at end of file diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php index b71e63030..d05e70aa9 100644 --- a/Zotlabs/Module/Admin/Site.php +++ b/Zotlabs/Module/Admin/Site.php @@ -48,6 +48,10 @@ class Site { $no_community_page = !((x($_POST,'no_community_page')) ? True : False); $default_expire_days = ((array_key_exists('default_expire_days',$_POST)) ? intval($_POST['default_expire_days']) : 0); + $reply_address = ((array_key_exists('reply_address',$_POST) && trim($_POST['reply_address'])) ? trim($_POST['reply_address']) : 'noreply@' . \App::get_hostname()); + $from_email = ((array_key_exists('from_email',$_POST) && trim($_POST['from_email'])) ? trim($_POST['from_email']) : 'Administrator@' . \App::get_hostname()); + $from_email_name = ((array_key_exists('from_email_name',$_POST) && trim($_POST['from_email_name'])) ? trim($_POST['from_email_name']) : \Zotlabs\Lib\System::get_site_name()); + $verifyssl = ((x($_POST,'verifyssl')) ? True : False); $proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : ''); $proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : ''); @@ -77,8 +81,15 @@ class Site { set_config('system', 'enable_context_help', $enable_context_help); set_config('system', 'verify_email', $verify_email); set_config('system', 'default_expire_days', $default_expire_days); + set_config('system', 'reply_address', $reply_address); + set_config('system', 'from_email', $from_email); + set_config('system', 'from_email_name' , $from_email_name); + + set_config('system', 'techlevel_lock', $techlevel_lock); + + if(! is_null($techlevel)) set_config('system', 'techlevel', $techlevel); @@ -304,6 +315,10 @@ class Site { '$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.")), + '$reply_address' => [ 'reply_address', t('Reply-to email address for system generated email.'), get_config('system','reply_address','noreply@' . \App::get_hostname()),'' ], + '$from_email' => [ 'from_email', t('Sender (From) email address for system generated email.'), get_config('system','from_email','Administrator@' . \App::get_hostname()),'' ], + '$from_email_name' => [ 'from_email_name', t('Name of email sender for system generated email.'), get_config('system','from_email_name',\Zotlabs\Lib\System::get_site_name()),'' ], + '$directory_server' => (($dir_choices) ? array('directory_server', t("Directory Server URL"), get_config('system','directory_server'), t("Default directory server"), $dir_choices) : null), '$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""), diff --git a/Zotlabs/Module/Admin/Themes.php b/Zotlabs/Module/Admin/Themes.php index fc908ec8b..8e72a1318 100644 --- a/Zotlabs/Module/Admin/Themes.php +++ b/Zotlabs/Module/Admin/Themes.php @@ -2,38 +2,41 @@ namespace Zotlabs\Module\Admin; +use \Michelf\MarkdownExtra; +/** + * @brief Admin area theme settings. + */ class Themes { + /** + * @brief + * + */ function post() { $theme = argv(2); if (is_file("view/theme/$theme/php/config.php")){ require_once("view/theme/$theme/php/config.php"); - // fixme add parent theme if derived - if (function_exists("theme_admin_post")){ + /// @FIXME add parent theme if derived + if (function_exists('theme_admin_post')){ theme_admin_post($a); } } info(t('Theme settings updated.')); - if(is_ajax()) + if(is_ajax()) return; - + goaway(z_root() . '/admin/themes/' . $theme ); } - - - /** * @brief Themes admin page. * - * @return string + * @return string with parsed HTML */ - function get(){ - $allowed_themes_str = get_config('system', 'allowed_themes'); $allowed_themes_raw = explode(',', $allowed_themes_str); $allowed_themes = array(); @@ -41,7 +44,7 @@ class Themes { foreach($allowed_themes_raw as $x) if(strlen(trim($x))) $allowed_themes[] = trim($x); - + $themes = array(); $files = glob('view/theme/*'); if($files) { @@ -53,56 +56,55 @@ class Themes { $themes[] = array('name' => $f, 'experimental' => $is_experimental, 'supported' => $is_supported, 'allowed' => $is_allowed); } } - + if(! count($themes)) { notice( t('No themes found.')); return ''; } - + /* * Single theme */ - + if (\App::$argc == 3){ $theme = \App::$argv[2]; if(! is_dir("view/theme/$theme")){ notice( t("Item not found.") ); return ''; } - + if (x($_GET,"a") && $_GET['a']=="t"){ check_form_security_token_redirectOnErr('/admin/themes', 'admin_themes', 't'); - + // Toggle theme status - + $this->toggle_theme($themes, $theme, $result); $s = $this->rebuild_theme_table($themes); if($result) info( sprintf('Theme %s enabled.', $theme)); else info( sprintf('Theme %s disabled.', $theme)); - + set_config('system', 'allowed_themes', $s); goaway(z_root() . '/admin/themes' ); } - + // display theme details - require_once('library/markdown.php'); - + if ($this->theme_status($themes,$theme)) { $status="on"; $action= t("Disable"); } else { $status="off"; $action= t("Enable"); } - + $readme=Null; if (is_file("view/theme/$theme/README.md")){ $readme = file_get_contents("view/theme/$theme/README.md"); - $readme = Markdown($readme); + $readme = MarkdownExtra::defaultTransform($readme); } else if (is_file("view/theme/$theme/README")){ - $readme = "<pre>". file_get_contents("view/theme/$theme/README") ."</pre>"; + $readme = '<pre>'. file_get_contents("view/theme/$theme/README") .'</pre>'; } - + $admin_form = ''; if (is_file("view/theme/$theme/php/config.php")){ require_once("view/theme/$theme/php/config.php"); @@ -110,11 +112,11 @@ class Themes { $admin_form = theme_admin($a); } } - + $screenshot = array( get_theme_screenshot($theme), t('Screenshot')); if(! stristr($screenshot[0],$theme)) $screenshot = null; - + $t = get_markup_template('admin_plugins_details.tpl'); return replace_macros($t, array( '$title' => t('Administration'), @@ -122,7 +124,7 @@ class Themes { '$toggle' => t('Toggle'), '$settings' => t('Settings'), '$baseurl' => z_root(), - + '$plugin' => $theme, '$status' => $status, '$action' => $action, @@ -133,22 +135,22 @@ class Themes { '$str_maintainer' => t('Maintainer: '), '$screenshot' => $screenshot, '$readme' => $readme, - + '$form_security_token' => get_form_security_token('admin_themes'), )); } - + /* * List themes */ - + $xthemes = array(); if($themes) { foreach($themes as $th) { $xthemes[] = array($th['name'],(($th['allowed']) ? "on" : "off"), get_theme_info($th['name'])); } } - + $t = get_markup_template('admin_plugins.tpl'); return replace_macros($t, array( '$title' => t('Administration'), @@ -162,13 +164,14 @@ class Themes { '$form_security_token' => get_form_security_token('admin_themes'), )); } - /** - * @param array $themes - * @param string $th - * @param int $result + * @brief Toggle a theme. + * + * @param array &$themes + * @param[in] string $th + * @param[out] int &$result */ function toggle_theme(&$themes, $th, &$result) { for($x = 0; $x < count($themes); $x ++) { @@ -184,7 +187,7 @@ class Themes { } } } - + /** * @param array $themes * @param string $th @@ -203,8 +206,7 @@ class Themes { } return 0; } - - + /** * @param array $themes * @return string @@ -222,12 +224,5 @@ class Themes { } return $o; } - - - - - - - } diff --git a/Zotlabs/Module/Bookmarks.php b/Zotlabs/Module/Bookmarks.php index 733bfd4e3..682f8e76c 100644 --- a/Zotlabs/Module/Bookmarks.php +++ b/Zotlabs/Module/Bookmarks.php @@ -68,7 +68,8 @@ class Bookmarks extends \Zotlabs\Web\Controller { $channel = \App::get_channel(); - $o = profile_tabs($a,true,$channel['channel_address']); + //$o = profile_tabs($a,true,$channel['channel_address']); + $o = ''; $o .= '<div class="generic-content-wrapper-styled">'; diff --git a/Zotlabs/Module/Cal.php b/Zotlabs/Module/Cal.php index b982d19a8..41676ce02 100644 --- a/Zotlabs/Module/Cal.php +++ b/Zotlabs/Module/Cal.php @@ -86,7 +86,8 @@ class Cal extends \Zotlabs\Web\Controller { $o = ''; - $tabs = profile_tabs($a, True, $channel['channel_address']); + //$tabs = profile_tabs($a, True, $channel['channel_address']); + $tabs = ''; $mode = 'view'; $y = 0; diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 0d20e0080..61df35a60 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -121,7 +121,7 @@ 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 .= profile_tabs($a, $is_owner, \App::$profile['channel_address']); $o .= common_friends_visitor_widget(\App::$profile['profile_uid']); @@ -321,6 +321,7 @@ class Channel extends \Zotlabs\Web\Controller { '$static' => $static, '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), '$search' => '', + '$xchan' => '', '$order' => '', '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$file' => '', diff --git a/Zotlabs/Module/Chat.php b/Zotlabs/Module/Chat.php index febfd51e5..23a3e65da 100644 --- a/Zotlabs/Module/Chat.php +++ b/Zotlabs/Module/Chat.php @@ -210,7 +210,8 @@ class Chat extends \Zotlabs\Web\Controller { require_once('include/conversation.php'); - $o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']); + //$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']); + $o = ''; if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) { notice( t('Feature disabled.') . EOL); diff --git a/Zotlabs/Module/Cloud.php b/Zotlabs/Module/Cloud.php index 2b6d7bcbe..7370eeda3 100644 --- a/Zotlabs/Module/Cloud.php +++ b/Zotlabs/Module/Cloud.php @@ -60,11 +60,9 @@ class Cloud extends \Zotlabs\Web\Controller { $_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']); $_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']); - $_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['QUERY_STRING']); $_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']); $_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']); - $_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['REQUEST_URI']); $rootDirectory = new \Zotlabs\Storage\Directory('/', $auth); diff --git a/Zotlabs/Module/Connections.php b/Zotlabs/Module/Connections.php index e8a92e8b7..b079ae860 100644 --- a/Zotlabs/Module/Connections.php +++ b/Zotlabs/Module/Connections.php @@ -5,10 +5,6 @@ namespace Zotlabs\Module; require_once('include/socgraph.php'); require_once('include/selectors.php'); require_once('include/group.php'); -require_once('include/contact_widgets.php'); -require_once('include/zot.php'); -require_once('include/widgets.php'); - class Connections extends \Zotlabs\Web\Controller { diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index 7a753c286..484e69b52 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -11,9 +11,6 @@ namespace Zotlabs\Module; require_once('include/socgraph.php'); require_once('include/selectors.php'); require_once('include/group.php'); -require_once('include/contact_widgets.php'); -require_once('include/zot.php'); -require_once('include/widgets.php'); require_once('include/photos.php'); @@ -391,30 +388,22 @@ class Connedit extends \Zotlabs\Web\Controller { $section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : ''); $channel = \App::get_channel(); - $my_perms = get_channel_default_perms(local_channel()); - $role = get_pconfig(local_channel(),'system','permissions_role'); - if($role) { - $x = \Zotlabs\Access\PermissionRoles::role_perms($role); - if($x['perms_connect']) - $my_perms = $x['perms_connect']; - } $yes_no = array(t('No'),t('Yes')); - if($my_perms) { - $o .= "<script>function connectDefaultShare() { - \$('.abook-edit-me').each(function() { - if(! $(this).is(':disabled')) - $(this).prop('checked', false); - });\n\n"; - $perms = get_perms(); - foreach($perms as $p => $v) { - if($my_perms & $v[1]) { - $o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n"; - } + $connect_perms = \Zotlabs\Access\Permissions::connect_perms(local_channel()); + + $o .= "<script>function connectDefaultShare() { + \$('.abook-edit-me').each(function() { + if(! $(this).is(':disabled')) + $(this).prop('checked', false); + });\n\n"; + foreach($connect_perms['perms'] as $p => $v) { + if($v) { + $o .= "\$('#me_id_perms_" . $p . "').prop('checked', true); \n"; } - $o .= " }\n</script>\n"; } + $o .= " }\n</script>\n"; if(argc() == 3) { @@ -441,6 +430,34 @@ class Connedit extends \Zotlabs\Web\Controller { goaway(z_root() . '/connedit/' . $contact_id); } + + if($cmd === 'fetchvc') { + $url = str_replace('/channel/','/profile/',$orig_record[0]['xchan_url']) . '/vcard'; + $recurse = 0; + $x = z_fetch_url(zid($url),false,$recurse,['session' => true]); + if($x['success']) { + $h = new \Zotlabs\Web\HTTPHeaders($x['header']); + $fields = $h->fetch(); + if($fields) { + foreach($fields as $y) { + if(array_key_exists('content-type',$y)) { + $type = explode(';',trim($y['content-type'])); + if($type && $type[0] === 'text/vcard' && $x['body']) { + $vc = \Sabre\VObject\Reader::read($x['body']); + $vcard = $vc->serialize(); + if($vcard) { + set_abconfig(local_channel(),$orig_record[0]['abook_xchan'],'system','vcard',$vcard); + $this->connedit_clone($a); + } + } + } + } + } + } + goaway(z_root() . '/connedit/' . $contact_id); + } + + if($cmd === 'resetphoto') { q("update xchan set xchan_photo_date = '2001-01-01 00:00:00' where xchan_hash = '%s'", dbesc($orig_record[0]['xchan_hash']) @@ -582,6 +599,13 @@ class Connedit extends \Zotlabs\Web\Controller { 'sel' => '', 'title' => t('Fetch updated permissions'), ), + + 'rephoto' => array( + 'label' => t('Refresh Photo'), + 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/resetphoto', + 'sel' => '', + 'title' => t('Fetch updated photo'), + ), 'recent' => array( 'label' => t('Recent Activity'), @@ -631,6 +655,17 @@ class Connedit extends \Zotlabs\Web\Controller { ); + + if($contact['xchan_network'] === 'zot') { + $tools['fetchvc'] = [ + 'label' => t('Fetch Vcard'), + 'url' => z_root() . '/connedit/' . $contact['abook_id'] . '/fetchvc', + 'sel' => '', + 'title' => t('Fetch electronic calling card for this connection') + ]; + } + + $sections = []; $sections['perms'] = [ diff --git a/Zotlabs/Module/Cover_photo.php b/Zotlabs/Module/Cover_photo.php index 72ec1020d..47bce6c2b 100644 --- a/Zotlabs/Module/Cover_photo.php +++ b/Zotlabs/Module/Cover_photo.php @@ -23,19 +23,17 @@ require_once('include/channel.php'); class Cover_photo extends \Zotlabs\Web\Controller { function init() { - if(! local_channel()) { return; } $channel = \App::get_channel(); - profile_load($channel['channel_address']); - + profile_load($channel['channel_address']); } - /* @brief Evaluate posted values + /** + * @brief Evaluate posted values * - * @param $a Current application * @return void * */ @@ -130,8 +128,15 @@ class Cover_photo extends \Zotlabs\Web\Controller { $aid = get_account_id(); - $p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'], - 'filename' => $base_image['filename'], 'album' => t('Cover Photos')); + $p = [ + 'aid' => $aid, + 'uid' => local_channel(), + 'resource_id' => $base_image['resource_id'], + 'filename' => $base_image['filename'], + 'album' => t('Cover Photos'), + 'os_path' => $base_image['os_path'], + 'display_path' => $base_image['display_path'] + ]; $p['imgscale'] = 7; $p['photo_usage'] = PHOTO_COVER; @@ -195,11 +200,10 @@ class Cover_photo extends \Zotlabs\Web\Controller { $os_storage = false; foreach($i as $ii) { - $smallest = intval($ii['imgscale']); + $smallest = intval($ii['imgscale']); $os_storage = intval($ii['os_storage']); - $imagedata = $ii['content']; - $filetype = $ii['mimetype']; - + $imagedata = $ii['content']; + $filetype = $ii['mimetype']; } } @@ -263,10 +267,10 @@ class Cover_photo extends \Zotlabs\Web\Controller { } - /* @brief Generate content of profile-photo view + /** + * @brief Generate content of profile-photo view * - * @param $a Current application - * @return void + * @return string * */ @@ -350,15 +354,15 @@ class Cover_photo extends \Zotlabs\Web\Controller { $tpl = get_markup_template('cover_photo.tpl'); $o .= replace_macros($tpl,array( - '$user' => \App::$channel['channel_address'], - '$lbl_upfile' => t('Upload File:'), - '$lbl_profiles' => t('Select a profile:'), - '$title' => t('Upload Cover Photo'), - '$submit' => t('Upload'), - '$profiles' => $profiles, + '$user' => \App::$channel['channel_address'], + '$lbl_upfile' => t('Upload File:'), + '$lbl_profiles' => t('Select a profile:'), + '$title' => t('Upload Cover Photo'), + '$submit' => t('Upload'), + '$profiles' => $profiles, '$form_security_token' => get_form_security_token("cover_photo"), - // FIXME - yuk - '$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . z_root() . '">' . t('skip this step') . '</a>' : '<a href="'. z_root() . '/photos/' . \App::$channel['channel_address'] . '">' . t('select a photo from your photo albums') . '</a>') + /// @FIXME - yuk + '$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . z_root() . '">' . t('skip this step') . '</a>' : '<a href="'. z_root() . '/photos/' . \App::$channel['channel_address'] . '">' . t('select a photo from your photo albums') . '</a>') )); call_hooks('cover_photo_content_end', $o); @@ -370,14 +374,14 @@ class Cover_photo extends \Zotlabs\Web\Controller { $resolution = 3; $tpl = get_markup_template("cropcover.tpl"); $o .= replace_macros($tpl,array( - '$filename' => $filename, - '$profile' => intval($_REQUEST['profile']), - '$resource' => \App::$data['imagecrop'] . '-3', - '$image_url' => z_root() . '/photo/' . $filename, - '$title' => t('Crop Image'), - '$desc' => t('Please adjust the image cropping for optimum viewing.'), + '$filename' => $filename, + '$profile' => intval($_REQUEST['profile']), + '$resource' => \App::$data['imagecrop'] . '-3', + '$image_url' => z_root() . '/photo/' . $filename, + '$title' => t('Crop Image'), + '$desc' => t('Please adjust the image cropping for optimum viewing.'), '$form_security_token' => get_form_security_token("cover_photo"), - '$done' => t('Done Editing') + '$done' => t('Done Editing') )); return $o; } @@ -393,8 +397,6 @@ class Cover_photo extends \Zotlabs\Web\Controller { * */ - - function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){ $max_length = get_config('system','max_image_length'); diff --git a/Zotlabs/Module/Directory.php b/Zotlabs/Module/Directory.php index 59ae88857..edcf43cd6 100644 --- a/Zotlabs/Module/Directory.php +++ b/Zotlabs/Module/Directory.php @@ -4,7 +4,6 @@ namespace Zotlabs\Module; require_once('include/socgraph.php'); require_once('include/dir_fns.php'); -require_once('include/widgets.php'); require_once('include/bbcode.php'); diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index a4d59a1b6..815672091 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -165,6 +165,7 @@ class Display extends \Zotlabs\Web\Controller { '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$search' => '', + '$xchan' => '', '$order' => '', '$file' => '', '$cats' => '', diff --git a/Zotlabs/Module/Editblock.php b/Zotlabs/Module/Editblock.php index 654e2251d..8a7e87a09 100644 --- a/Zotlabs/Module/Editblock.php +++ b/Zotlabs/Module/Editblock.php @@ -98,6 +98,11 @@ class Editblock extends \Zotlabs\Web\Controller { $mimetype = $itm[0]['mimetype']; + $content = $itm[0]['body']; + if($itm[0]['mimetype'] === 'text/markdown') + $content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']); + + $rp = 'blocks/' . $channel['channel_address']; $x = array( @@ -117,7 +122,7 @@ class Editblock extends \Zotlabs\Web\Controller { 'ptyp' => $itm[0]['type'], 'mimeselect' => true, 'mimetype' => $itm[0]['mimetype'], - 'body' => undo_post_tagging($itm[0]['body']), + 'body' => undo_post_tagging($content), 'post_id' => $post_id, 'visitor' => true, 'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'), diff --git a/Zotlabs/Module/Editlayout.php b/Zotlabs/Module/Editlayout.php index ea637fcba..3d6a79507 100644 --- a/Zotlabs/Module/Editlayout.php +++ b/Zotlabs/Module/Editlayout.php @@ -119,6 +119,7 @@ class Editlayout extends \Zotlabs\Web\Controller { 'hide_weblink' => true, 'hide_attach' => true, 'hide_preview' => true, + 'disable_comments' => true, 'ptyp' => $itm[0]['obj_type'], 'body' => undo_post_tagging($itm[0]['body']), 'post_id' => $post_id, diff --git a/Zotlabs/Module/Editpost.php b/Zotlabs/Module/Editpost.php index d7612b165..629bdd3fd 100644 --- a/Zotlabs/Module/Editpost.php +++ b/Zotlabs/Module/Editpost.php @@ -31,7 +31,10 @@ class Editpost extends \Zotlabs\Web\Controller { dbesc(get_observer_hash()) ); - if(! count($itm)) { + // don't allow web editing of potentially binary content (item_obscured = 1) + // @FIXME how do we do it instead? + + if((! $itm) || intval($itm[0]['item_obscured'])) { notice( t('Item is not editable') . EOL); return; } @@ -44,14 +47,6 @@ class Editpost extends \Zotlabs\Web\Controller { $channel = \App::get_channel(); - if(intval($itm[0]['item_obscured'])) { - $key = get_config('system','prvkey'); - if($itm[0]['title']) - $itm[0]['title'] = crypto_unencapsulate(json_decode($itm[0]['title'],true),$key); - if($itm[0]['body']) - $itm[0]['body'] = crypto_unencapsulate(json_decode($itm[0]['body'],true),$key); - } - $category = ''; $catsenabled = ((feature_enabled($owner_uid,'categories')) ? 'categories' : ''); diff --git a/Zotlabs/Module/Editwebpage.php b/Zotlabs/Module/Editwebpage.php index 97f4a32ff..db33cd1db 100644 --- a/Zotlabs/Module/Editwebpage.php +++ b/Zotlabs/Module/Editwebpage.php @@ -100,19 +100,14 @@ class Editwebpage extends \Zotlabs\Web\Controller { intval($owner) ); - if(! $itm) { + // don't allow web editing of potentially binary content (item_obscured = 1) + // @FIXME how do we do it instead? + + if((! $itm) || intval($itm[0]['item_obscured'])) { notice( t('Permission denied.') . EOL); return; } - if(intval($itm[0]['item_obscured'])) { - $key = get_config('system','prvkey'); - if($itm[0]['title']) - $itm[0]['title'] = crypto_unencapsulate(json_decode($itm[0]['title'],true),$key); - if($itm[0]['body']) - $itm[0]['body'] = crypto_unencapsulate(json_decode($itm[0]['body'],true),$key); - } - $item_id = q("select * from iconfig where cat = 'system' and k = 'WEBPAGE' and iid = %d limit 1", intval($itm[0]['id']) ); @@ -129,6 +124,10 @@ class Editwebpage extends \Zotlabs\Web\Controller { } $layout = $itm[0]['layout_mid']; + + $content = $itm[0]['body']; + if($itm[0]['mimetype'] === 'text/markdown') + $content = \Zotlabs\Lib\MarkdownSoap::unescape($itm[0]['body']); $rp = 'webpages/' . $which; @@ -145,7 +144,7 @@ class Editwebpage extends \Zotlabs\Web\Controller { 'hide_location' => true, 'hide_voting' => true, 'ptyp' => $itm[0]['type'], - 'body' => undo_post_tagging($itm[0]['body']), + 'body' => undo_post_tagging($content), 'post_id' => $post_id, 'visitor' => ($is_owner) ? true : false, 'acl' => populate_acl($itm[0],false,\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')), diff --git a/Zotlabs/Module/Embedphotos.php b/Zotlabs/Module/Embedphotos.php index 48667795c..c92af27d6 100644 --- a/Zotlabs/Module/Embedphotos.php +++ b/Zotlabs/Module/Embedphotos.php @@ -92,6 +92,7 @@ class Embedphotos extends \Zotlabs\Web\Controller { * It is a limitation of the photo table using a name for a photo album instead of a folder hash */ if($album) { + require_once('include/attach.php'); $x = q("select hash from attach where filename = '%s' and uid = %d limit 1", dbesc($album), intval($owner_uid) diff --git a/Zotlabs/Module/Feed.php b/Zotlabs/Module/Feed.php index 47871eafb..06637b6d2 100644 --- a/Zotlabs/Module/Feed.php +++ b/Zotlabs/Module/Feed.php @@ -1,40 +1,41 @@ <?php + namespace Zotlabs\Module; require_once('include/items.php'); - class Feed extends \Zotlabs\Web\Controller { function init() { - $params = array(); - - $params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE); - $params['end'] = ((x($_REQUEST,'date_end')) ? $_REQUEST['date_end'] : ''); - $params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml'); - $params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0); - $params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0); - $params['start'] = ((x($params,'start')) ? intval($params['start']) : 0); - $params['records'] = ((x($params,'records')) ? intval($params['records']) : 40); - $params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc'); - $params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : ''); - - $channel = ''; + $params = []; + + $params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE); + $params['end'] = ((x($_REQUEST,'date_end')) ? $_REQUEST['date_end'] : ''); + $params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml'); + $params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0); + $params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0); + $params['start'] = ((x($params,'start')) ? intval($params['start']) : 0); + $params['records'] = ((x($params,'records')) ? intval($params['records']) : 40); + $params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc'); + $params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : ''); + $params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 0); + + if(argc() > 1) { - $r = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_address = '%s' limit 1", - dbesc(argv(1)) - ); - if(!($r && count($r))) + + if(observer_prohibited(true)) { killme(); - - $channel = $r[0]; - - if(observer_prohibited(true)) + } + + $channel = channelx_by_nick(argv(1)); + if(! $channel) { killme(); + } + - logger('mod_feed: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']); + logger('public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']); echo get_public_feed($channel,$params); @@ -43,6 +44,4 @@ class Feed extends \Zotlabs\Web\Controller { } - - } diff --git a/Zotlabs/Module/File_upload.php b/Zotlabs/Module/File_upload.php index 769134808..29a7bd137 100644 --- a/Zotlabs/Module/File_upload.php +++ b/Zotlabs/Module/File_upload.php @@ -28,11 +28,12 @@ class File_upload extends \Zotlabs\Web\Controller { $_REQUEST['group_deny'] = expand_acl($channel['channel_deny_gid']); } + $_REQUEST['allow_cid'] = perms2str($_REQUEST['contact_allow']); + $_REQUEST['allow_gid'] = perms2str($_REQUEST['group_allow']); + $_REQUEST['deny_cid'] = perms2str($_REQUEST['contact_deny']); + $_REQUEST['deny_gid'] = perms2str($_REQUEST['group_deny']); + if($_REQUEST['filename']) { - $_REQUEST['allow_cid'] = perms2str($_REQUEST['contact_allow']); - $_REQUEST['allow_gid'] = perms2str($_REQUEST['group_allow']); - $_REQUEST['deny_cid'] = perms2str($_REQUEST['contact_deny']); - $_REQUEST['deny_gid'] = perms2str($_REQUEST['group_deny']); $r = attach_mkdir($channel,get_observer_hash(),$_REQUEST); } else { diff --git a/Zotlabs/Module/Filer.php b/Zotlabs/Module/Filer.php index 6a57cdb2a..af59f28fb 100644 --- a/Zotlabs/Module/Filer.php +++ b/Zotlabs/Module/Filer.php @@ -49,8 +49,10 @@ class Filer extends \Zotlabs\Web\Controller { } $tpl = get_markup_template("filer_dialog.tpl"); $o = replace_macros($tpl, array( - '$field' => array('term', t("Save to Folder:"), '', '', $filetags, t('- select -')), + '$field' => array('term', t('Enter a folder name'), '', '', $filetags, 'placeholder="' . t('or select an existing folder (doubleclick)') . '"'), '$submit' => t('Save'), + '$title' => t('Save to Folder'), + '$cancel' => t('Cancel') )); echo $o; diff --git a/Zotlabs/Module/Filestorage.php b/Zotlabs/Module/Filestorage.php index 874445145..785dff394 100644 --- a/Zotlabs/Module/Filestorage.php +++ b/Zotlabs/Module/Filestorage.php @@ -130,7 +130,7 @@ class Filestorage extends \Zotlabs\Web\Controller { $f = $r[0]; $channel = \App::get_channel(); - $cloudpath = get_cloudpath($f) . (intval($f['is_dir']) ? '?f=&davguest=1' : ''); + $cloudpath = get_cloudpath($f); $parentpath = get_parent_cloudpath($channel['channel_id'], $channel['channel_address'], $f['hash']); $aclselect_e = populate_acl($f, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')); diff --git a/Zotlabs/Module/Hcard.php b/Zotlabs/Module/Hcard.php index ec9181f6a..13097939e 100644 --- a/Zotlabs/Module/Hcard.php +++ b/Zotlabs/Module/Hcard.php @@ -59,12 +59,10 @@ class Hcard extends \Zotlabs\Web\Controller { } - function get() { - - require_once('include/widgets.php'); - return widget_profile(array()); - - + function get() { + + $x = new \Zotlabs\Widget\Profile(); + return $x->widget(array()); } diff --git a/Zotlabs/Module/Impel.php b/Zotlabs/Module/Impel.php index 197d9f859..77f488d26 100644 --- a/Zotlabs/Module/Impel.php +++ b/Zotlabs/Module/Impel.php @@ -144,18 +144,8 @@ class Impel extends \Zotlabs\Web\Controller { // Verify ability to use html or php!!! - $execflag = false; - - if($arr['mimetype'] === 'application/x-php') { - $z = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1", - intval(local_channel()) - ); - - if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) { - $execflag = true; - } - } - + $execflag = ((intval($channel['channel_id']) == intval(local_channel()) && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false); + $i = q("select id, edited, item_deleted from item where mid = '%s' and uid = %d limit 1", dbesc($arr['mid']), intval(local_channel()) diff --git a/Zotlabs/Module/Import.php b/Zotlabs/Module/Import.php index 3969f25e0..ce3fd469a 100644 --- a/Zotlabs/Module/Import.php +++ b/Zotlabs/Module/Import.php @@ -2,26 +2,32 @@ namespace Zotlabs\Module; -// Import a channel, either by direct file upload or via -// connection to original server. - - require_once('include/zot.php'); require_once('include/channel.php'); require_once('include/import.php'); require_once('include/perm_upgrade.php'); - +/** + * @brief Module for channel import. + * + * Import a channel, either by direct file upload or via + * connection to another server. + */ class Import extends \Zotlabs\Web\Controller { + /** + * @brief Import channel into account. + * + * @param int $account_id + */ function import_account($account_id) { - + if(! $account_id){ - logger("import_account: No account ID supplied"); + logger('No account ID supplied'); return; } - + $max_friends = account_service_class_fetch($account_id,'total_channels'); $max_feeds = account_service_class_fetch($account_id,'total_feeds'); $data = null; @@ -32,35 +38,39 @@ class Import extends \Zotlabs\Web\Controller { $filename = basename($_FILES['filename']['name']); $filesize = intval($_FILES['filename']['size']); $filetype = $_FILES['filename']['type']; - + // import channel from file if($src) { - - // This is OS specific and could also fail if your tmpdir isn't very large - // mostly used for Diaspora which exports gzipped files. - + + // This is OS specific and could also fail if your tmpdir isn't very + // large mostly used for Diaspora which exports gzipped files. + if(strpos($filename,'.gz')){ @rename($src,$src . '.gz'); @system('gunzip ' . escapeshellarg($src . '.gz')); } - + if($filesize) { $data = @file_get_contents($src); } unlink($src); } - + + // import channel from another server if(! $src) { $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : ''); if(! $old_address) { - logger('mod_import: nothing to import.'); + logger('Nothing to import.'); notice( t('Nothing to import.') . EOL); return; + } else if(strpos($old_address, 'ï¼ ')) { + // if you copy the identity address from your profile page, make it work for convenience + $old_address = str_replace('ï¼ ', '@', $old_address); } - + $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : ''); $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : ''); - + $channelname = substr($old_address,0,strpos($old_address,'@')); $servername = substr($old_address,strpos($old_address,'@')+1); @@ -73,6 +83,7 @@ class Import extends \Zotlabs\Web\Controller { $api_path .= 'channel/export/basic?f=&channel=' . $channelname; if($import_posts) $api_path .= '&posts=1'; + $binary = false; $redirects = 0; $opts = array('http_auth' => $email . ':' . $password); @@ -85,19 +96,18 @@ class Import extends \Zotlabs\Web\Controller { return; } } - + if(! $data) { - logger('mod_import: empty file.'); + logger('Empty import file.'); notice( t('Imported file is empty.') . EOL); return; } - + $data = json_decode($data,true); - - // logger('import: data: ' . print_r($data,true)); - // print_r($data); - - + + //logger('import: data: ' . print_r($data,true)); + //print_r($data); + if(! array_key_exists('compatibility',$data)) { call_hooks('import_foreign_channel_data',$data); if($data['handled']) @@ -108,24 +118,24 @@ class Import extends \Zotlabs\Web\Controller { $v1 = substr($data['compatibility']['database'],-4); $v2 = substr(DB_UPDATE_VERSION,-4); if($v2 > $v1) { - $t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 ); + $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) $seize = 1; - + // import channel - + $relocate = ((array_key_exists('relocate',$data)) ? $data['relocate'] : null); if(array_key_exists('channel',$data)) { - + $max_identities = account_service_class_fetch($account_id,'total_identities'); - + if($max_identities !== false) { $r = q("select channel_id from channel where channel_account_id = %d", intval($account_id) @@ -137,46 +147,40 @@ class Import extends \Zotlabs\Web\Controller { } $channel = import_channel($data['channel'], $account_id, $seize); - } else { $moving = false; $channel = \App::get_channel(); } - + if(! $channel) { - logger('mod_import: channel not found. ', print_r($channel,true)); + logger('Channel not found. ', print_r($channel,true)); notice( t('No channel. Import failed.') . EOL); return; } - - if(is_array($data['config'])) { import_config($channel,$data['config']); } - + logger('import step 2'); - - - if(array_key_exists('channel',$data)) { if($data['photo']) { require_once('include/photo/photo_driver.php'); import_channel_photo(base64url_decode($data['photo']['data']),$data['photo']['type'],$account_id,$channel['channel_id']); } - + if(is_array($data['profile'])) import_profiles($channel,$data['profile']); } - + logger('import step 3'); - + if(is_array($data['hubloc'])) { import_hublocs($channel,$data['hubloc'],$seize,$moving); } - + logger('import step 4'); // create new hubloc for the new channel at this site @@ -200,7 +204,7 @@ class Import extends \Zotlabs\Web\Controller { ); // reset the original primary hubloc if it is being seized - + if($seize) { $r = q("update hubloc set hubloc_primary = 0 where hubloc_primary = 1 and hubloc_hash = '%s' and hubloc_url != '%s' ", dbesc($channel['channel_hash']), @@ -210,20 +214,18 @@ class Import extends \Zotlabs\Web\Controller { } logger('import step 5'); - - - + + // import xchans and contact photos - + if(array_key_exists('channel',$data) && $seize) { - + // replace any existing xchan we may have on this site if we're seizing control - + $r = q("delete from xchan where xchan_hash = '%s'", dbesc($channel['channel_hash']) ); - $r = xchan_store_lowlevel( [ 'xchan_hash' => $channel['channel_hash'], @@ -242,23 +244,22 @@ class Import extends \Zotlabs\Web\Controller { 'xchan_photo_date' => datetime_convert(), 'xchan_name_date' => datetime_convert() ] - ); + ); } - + logger('import step 6'); - - + // import xchans $xchans = $data['xchan']; if($xchans) { foreach($xchans as $xchan) { - + $hash = make_xchan_hash($xchan['xchan_guid'],$xchan['xchan_guid_sig']); if($xchan['xchan_network'] === 'zot' && $hash !== $xchan['xchan_hash']) { logger('forged xchan: ' . print_r($xchan,true)); continue; } - + if(! array_key_exists('xchan_hidden',$xchan)) { $xchan['xchan_hidden'] = (($xchan['xchan_flags'] & 0x0001) ? 1 : 0); $xchan['xchan_orphan'] = (($xchan['xchan_flags'] & 0x0002) ? 1 : 0); @@ -268,22 +269,22 @@ class Import extends \Zotlabs\Web\Controller { $xchan['xchan_pubforum'] = (($xchan['xchan_flags'] & 0x0020) ? 1 : 0); $xchan['xchan_deleted'] = (($xchan['xchan_flags'] & 0x1000) ? 1 : 0); } - + $r = q("select xchan_hash from xchan where xchan_hash = '%s' limit 1", dbesc($xchan['xchan_hash']) ); if($r) continue; - create_table_from_array('xchan',$xchan); - + create_table_from_array('xchan',$xchan); + require_once('include/photo/photo_driver.php'); $photos = import_xchan_photo($xchan['xchan_photo_l'],$xchan['xchan_hash']); if($photos[4]) $photodate = NULL_DATE; else $photodate = $xchan['xchan_photo_date']; - + $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'", dbesc($photos[0]), dbesc($photos[1]), @@ -292,33 +293,32 @@ class Import extends \Zotlabs\Web\Controller { dbesc($photodate), dbesc($xchan['xchan_hash']) ); - } - logger('import step 7'); + logger('import step 7'); } - $friends = 0; $feeds = 0; - + // import contacts $abooks = $data['abook']; if($abooks) { foreach($abooks as $abook) { $abook_copy = $abook; - + $abconfig = null; if(array_key_exists('abconfig',$abook) && is_array($abook['abconfig']) && count($abook['abconfig'])) $abconfig = $abook['abconfig']; - + unset($abook['abook_id']); unset($abook['abook_rating']); unset($abook['abook_rating_text']); unset($abook['abconfig']); unset($abook['abook_their_perms']); unset($abook['abook_my_perms']); + unset($abook['abook_not_here']); $abook['abook_account'] = $account_id; $abook['abook_channel'] = $channel['channel_id']; @@ -332,7 +332,7 @@ class Import extends \Zotlabs\Web\Controller { $abook['abook_self'] = (($abook['abook_flags'] & 0x0080 ) ? 1 : 0); $abook['abook_feed'] = (($abook['abook_flags'] & 0x0100 ) ? 1 : 0); } - + if($abook['abook_self']) { $role = get_pconfig($channel['channel_id'],'system','permissions_role'); if(($role === 'forum') || ($abook['abook_my_perms'] & PERMS_W_TAGWALL)) { @@ -340,24 +340,24 @@ class Import extends \Zotlabs\Web\Controller { dbesc($abook['abook_xchan']) ); } - } + } else { if($max_friends !== false && $friends > $max_friends) continue; if($max_feeds !== false && intval($abook['abook_feed']) && ($feeds > $max_feeds)) continue; } - - create_table_from_array('abook',$abook); + + abook_store_lowlevel($abook); $friends ++; if(intval($abook['abook_feed'])) $feeds ++; translate_abook_perms_inbound($channel,$abook_copy); - + if($abconfig) { - // @fixme does not handle sync of del_abconfig + /// @FIXME does not handle sync of del_abconfig foreach($abconfig as $abc) { set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']); } @@ -366,20 +366,21 @@ class Import extends \Zotlabs\Web\Controller { logger('import step 8'); } - + + // import groups $groups = $data['group']; if($groups) { $saved = array(); foreach($groups as $group) { $saved[$group['hash']] = array('old' => $group['id']); - if(array_key_exists('name',$group)) { + if(array_key_exists('name', $group)) { $group['gname'] = $group['name']; unset($group['name']); } unset($group['id']); $group['uid'] = $channel['channel_id']; - create_table_from_array('groups',$group); + create_table_from_array('groups', $group); } $r = q("select * from groups where uid = %d", intval($channel['channel_id']) @@ -388,10 +389,10 @@ class Import extends \Zotlabs\Web\Controller { foreach($r as $rr) { $saved[$rr['hash']]['new'] = $rr['id']; } - } + } } - - + + // import group members $group_members = $data['group_member']; if($group_members) { foreach($group_members as $group_member) { @@ -401,36 +402,36 @@ class Import extends \Zotlabs\Web\Controller { if($x['old'] == $group_member['gid']) $group_member['gid'] = $x['new']; } - create_table_from_array('group_member',$group_member); + create_table_from_array('group_member', $group_member); } } logger('import step 9'); - + if(is_array($data['obj'])) import_objs($channel,$data['obj']); - + if(is_array($data['likes'])) import_likes($channel,$data['likes']); - + if(is_array($data['app'])) import_apps($channel,$data['app']); - + if(is_array($data['chatroom'])) import_chatrooms($channel,$data['chatroom']); - + if(is_array($data['conv'])) import_conv($channel,$data['conv']); - + if(is_array($data['mail'])) import_mail($channel,$data['mail']); - + if(is_array($data['event'])) import_events($channel,$data['event']); - + if(is_array($data['event_item'])) import_items($channel,$data['event_item'],false,$relocate); - + if(is_array($data['menu'])) import_menus($channel,$data['menu']); @@ -439,56 +440,62 @@ class Import extends \Zotlabs\Web\Controller { if(is_array($data['webpages'])) import_items($channel,$data['webpages'],false,$relocate); - + $addon = array('channel' => $channel,'data' => $data); call_hooks('import_channel',$addon); - + $saved_notification_flags = notifications_off($channel['channel_id']); - + if($import_posts && array_key_exists('item',$data) && $data['item']) import_items($channel,$data['item'],false,$relocate); - + notifications_on($channel['channel_id'],$saved_notification_flags); - - + if(array_key_exists('item_id',$data) && $data['item_id']) import_item_ids($channel,$data['item_id']); - + // send out refresh requests // notify old server that it may no longer be primary. - + \Zotlabs\Daemon\Master::Summon(array('Notifier','location',$channel['channel_id'])); - + // This will indirectly perform a refresh_all *and* update the directory - + \Zotlabs\Daemon\Master::Summon(array('Directory', $channel['channel_id'])); - - + + notice( t('Import completed.') . EOL); - + change_channel($channel['channel_id']); - + goaway(z_root() . '/network' ); - } - - + + /** + * @brief Handle POST action on channel import page. + */ function post() { - $account_id = get_account_id(); if(! $account_id) return; - + + check_form_security_token_redirectOnErr('/import', 'channel_import'); + $this->import_account($account_id); } - + + /** + * @brief Generate channel import page. + * + * @return string with parsed HTML. + */ function get() { - + if(! get_account_id()) { - notice( t('You must be logged in to use this feature.')); + notice( t('You must be logged in to use this feature.') . EOL); return ''; } - + $o = replace_macros(get_markup_template('channel_import.tpl'),array( '$title' => t('Import Channel'), '$desc' => t('Use this form to import an existing channel from a different server/hub. You may retrieve the channel identity from the old server/hub via the network or provide an export file.'), @@ -501,14 +508,14 @@ class Import extends \Zotlabs\Web\Controller { '$label_import_primary' => t('Make this hub my primary location'), '$label_import_moving' => t('Move this channel (disable all previous locations)'), '$label_import_posts' => t('Import a few months of posts if possible (limited by available memory'), - '$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'), + '$pleasewait' => t('This process may take several minutes to complete. Please submit the form only once and leave this page open until finished.'), '$email' => '', '$pass' => '', + '$form_security_token' => get_form_security_token('channel_import'), '$submit' => t('Submit') )); - + return $o; - } - + } diff --git a/Zotlabs/Module/Import_items.php b/Zotlabs/Module/Import_items.php index f20cbfe7e..c2b2506fe 100644 --- a/Zotlabs/Module/Import_items.php +++ b/Zotlabs/Module/Import_items.php @@ -3,54 +3,60 @@ namespace Zotlabs\Module; require_once('include/import.php'); - +/** + * @brief Module for importing items. + * + * Import existing posts and content from an export file. + */ class Import_items extends \Zotlabs\Web\Controller { function post() { - + if(! local_channel()) return; - + + check_form_security_token_redirectOnErr('/import_items', 'import_items'); + $data = null; - + $src = $_FILES['filename']['tmp_name']; $filename = basename($_FILES['filename']['name']); $filesize = intval($_FILES['filename']['size']); $filetype = $_FILES['filename']['type']; - + if($src) { // This is OS specific and could also fail if your tmpdir isn't very large // mostly used for Diaspora which exports gzipped files. - + if(strpos($filename,'.gz')){ @rename($src,$src . '.gz'); @system('gunzip ' . escapeshellarg($src . '.gz')); } - + if($filesize) { $data = @file_get_contents($src); } unlink($src); } - + if(! $src) { - + $old_address = ((x($_REQUEST,'old_address')) ? $_REQUEST['old_address'] : ''); - + if(! $old_address) { - logger('mod_import: nothing to import.'); + logger('Nothing to import.'); notice( t('Nothing to import.') . EOL); return; } - + $email = ((x($_REQUEST,'email')) ? $_REQUEST['email'] : ''); $password = ((x($_REQUEST,'password')) ? $_REQUEST['password'] : ''); - + $year = ((x($_REQUEST,'year')) ? $_REQUEST['year'] : ''); - + $channelname = substr($old_address,0,strpos($old_address,'@')); $servername = substr($old_address,strpos($old_address,'@')+1); - + $scheme = 'https://'; $api_path = '/api/red/channel/export/items?f=&channel=' . $channelname . '&year=' . intval($year); $binary = false; @@ -64,68 +70,66 @@ class Import_items extends \Zotlabs\Web\Controller { $data = $ret['body']; else notice( t('Unable to download data from old server') . EOL); - } - + if(! $data) { - logger('mod_import: empty file.'); + logger('Empty file.'); notice( t('Imported file is empty.') . EOL); return; } - - $data = json_decode($data,true); - - // logger('import: data: ' . print_r($data,true)); - // print_r($data); - + + $data = json_decode($data, true); + + //logger('import: data: ' . print_r($data,true)); + //print_r($data); + if(! is_array($data)) return; - + if(array_key_exists('compatibility',$data) && array_key_exists('database',$data['compatibility'])) { $v1 = substr($data['compatibility']['database'],-4); $v2 = substr(DB_UPDATE_VERSION,-4); if($v2 > $v1) { - $t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 ); - notice($t); + $t = sprintf( t('Warning: Database versions differ by %1$d updates.'), $v2 - $v1 ); + notice($t . EOL); } } - + $channel = \App::get_channel(); - - + if(array_key_exists('item',$data) && $data['item']) { import_items($channel,$data['item'],false,((array_key_exists('relocate',$data)) ? $data['relocate'] : null)); } - + if(array_key_exists('item_id',$data) && $data['item_id']) { import_item_ids($channel,$data['item_id']); } - + info( t('Import completed') . EOL); - return; } - - - - + + + /** + * @brief Generate item import page. + * + * @return string with parsed HTML. + */ function get() { - + if(! local_channel()) { notice( t('Permission denied') . EOL); return login(); } - - $o = replace_macros(get_markup_template('item_import.tpl'),array( + + $o = replace_macros(get_markup_template('item_import.tpl'), array( '$title' => t('Import Items'), '$desc' => t('Use this form to import existing posts and content from an export file.'), '$label_filename' => t('File to Upload'), + '$form_security_token' => get_form_security_token('import_items'), '$submit' => t('Submit') )); - + return $o; - } - - - + } diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php index 6f54d3bb1..ec36c22d8 100644 --- a/Zotlabs/Module/Item.php +++ b/Zotlabs/Module/Item.php @@ -110,6 +110,7 @@ class Item extends \Zotlabs\Web\Controller { $preview = ((x($_REQUEST,'preview')) ? intval($_REQUEST['preview']) : 0); $categories = ((x($_REQUEST,'category')) ? escape_tags($_REQUEST['category']) : ''); $webpage = ((x($_REQUEST,'webpage')) ? intval($_REQUEST['webpage']) : 0); + $item_obscured = ((x($_REQUEST,'obscured')) ? intval($_REQUEST['obscured']) : 0); $pagetitle = ((x($_REQUEST,'pagetitle')) ? escape_tags(urlencode($_REQUEST['pagetitle'])) : ''); $layout_mid = ((x($_REQUEST,'layout_mid')) ? escape_tags($_REQUEST['layout_mid']): ''); $plink = ((x($_REQUEST,'permalink')) ? escape_tags($_REQUEST['permalink']) : ''); @@ -471,24 +472,16 @@ class Item extends \Zotlabs\Web\Controller { if(! $mimetype) $mimetype = 'text/bbcode'; + + $execflag = ((intval($uid) == intval($profile_uid) + && ($channel['channel_pageflags'] & PAGE_ALLOWCODE)) ? true : false); + if($preview) { - $body = z_input_filter($profile_uid,$body,$mimetype); + $body = z_input_filter($body,$mimetype,$execflag); } - // Verify ability to use html or php!!! - $execflag = false; - - $z = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1", - intval($profile_uid) - ); - if($z && (($z[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($z[0]['channel_pageflags'] & PAGE_ALLOWCODE))) { - if($uid && (get_account_id() == $z[0]['account_id'])) { - $execflag = true; - } - } - $gacl = $acl->get(); $str_contact_allow = $gacl['allow_cid']; $str_group_allow = $gacl['allow_gid']; @@ -852,18 +845,6 @@ class Item extends \Zotlabs\Web\Controller { if(mb_strlen($datarray['title']) > 255) $datarray['title'] = mb_substr($datarray['title'],0,255); - if(array_key_exists('item_private',$datarray) && $datarray['item_private']) { - - $datarray['body'] = trim(z_input_filter($datarray['uid'],$datarray['body'],$datarray['mimetype'])); - - if($uid) { - if($channel['channel_hash'] === $datarray['author_xchan']) { - $datarray['sig'] = base64url_encode(rsa_sign($datarray['body'],$channel['channel_prvkey'])); - $datarray['item_verified'] = 1; - } - } - } - if($webpage) { Zlib\IConfig::Set($datarray,'system', webpage_to_namespace($webpage), (($pagetitle) ? $pagetitle : substr($datarray['mid'],0,16)),true); @@ -879,7 +860,17 @@ class Item extends \Zotlabs\Web\Controller { $x = item_store_update($datarray,$execflag); - item_create_edit_activity($x); + // We only need edit activities for other federated protocols + // which do not support edits natively. While this does federate + // edits, it presents a number of issues locally - such as #757 and #758. + // The SQL check for an edit activity would not perform that well so to fix these issues + // requires an additional item flag (perhaps 'item_edit_activity') that we can add to the + // query for searches and notifications. + + // For now we'll just forget about trying to make edits work on network protocols that + // don't support them. + + // item_create_edit_activity($x); if(! $parent) { $r = q("select * from item where id = %d", diff --git a/Zotlabs/Module/Layouts.php b/Zotlabs/Module/Layouts.php index c07f65ce1..34d754029 100644 --- a/Zotlabs/Module/Layouts.php +++ b/Zotlabs/Module/Layouts.php @@ -125,6 +125,7 @@ class Layouts extends \Zotlabs\Web\Controller { 'hide_weblink' => true, 'hide_attach' => true, 'hide_preview' => true, + 'disable_comments' => true, 'ptlabel' => t('Layout Name'), 'profile_uid' => intval($owner), 'expanded' => true, diff --git a/Zotlabs/Module/Lockview.php b/Zotlabs/Module/Lockview.php index fc7d5c7c8..466d16997 100644 --- a/Zotlabs/Module/Lockview.php +++ b/Zotlabs/Module/Lockview.php @@ -72,7 +72,7 @@ class Lockview extends \Zotlabs\Web\Controller { } if($uid != local_channel()) { - echo '<li>' . t('Remote privacy information not available.') . '</li>'; + echo '<div class="dropdown-item">' . t('Remote privacy information not available.') . '</div>'; killme(); } @@ -84,7 +84,7 @@ class Lockview extends \Zotlabs\Web\Controller { // as unknown specific recipients. The sender will have the visibility list and will fall through to the // next section. - echo '<li>' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</li>'; + echo '<div class="dropdown-item">' . translate_scope((! $item['public_policy']) ? 'specific' : $item['public_policy']) . '</div>'; killme(); } @@ -93,7 +93,7 @@ class Lockview extends \Zotlabs\Web\Controller { $deny_users = expand_acl($item['deny_cid']); $deny_groups = expand_acl($item['deny_gid']); - $o = '<li>' . t('Visible to:') . '</li>'; + $o = '<div class="dropdown-item">' . t('Visible to:') . '</div>'; $l = array(); stringify_array_elms($allowed_groups,true); @@ -114,24 +114,24 @@ class Lockview extends \Zotlabs\Web\Controller { $r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )"); if($r) foreach($r as $rr) - $l[] = '<li><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></li>'; + $l[] = '<div class="dropdown-item"><b>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</b></div>'; } if(count($allowed_groups)) { $r = q("SELECT gname FROM groups WHERE hash IN ( " . implode(', ', $allowed_groups) . " )"); if($r) foreach($r as $rr) - $l[] = '<li><b>' . $rr['gname'] . '</b></li>'; + $l[] = '<div class="dropdown-item"><b>' . $rr['gname'] . '</b></div>'; } if(count($allowed_users)) { $r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ',$allowed_users) . " )"); if($r) foreach($r as $rr) - $l[] = '<li>' . $rr['xchan_name'] . '</li>'; + $l[] = '<div class="dropdown-item">' . $rr['xchan_name'] . '</div>'; if($atokens) { foreach($atokens as $at) { if(in_array("'" . $at['xchan_hash'] . "'",$allowed_users)) { - $l[] = '<li>' . $at['xchan_name'] . '</li>'; + $l[] = '<div class="dropdown-item">' . $at['xchan_name'] . '</div>'; } } } @@ -150,7 +150,7 @@ class Lockview extends \Zotlabs\Web\Controller { $r = q("SELECT profile_name FROM profile WHERE profile_guid IN ( " . implode(', ', $profile_groups) . " )"); if($r) foreach($r as $rr) - $l[] = '<li><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></li>'; + $l[] = '<div class="dropdown-item"><b><strike>' . t('Profile','acl') . ' ' . $rr['profile_name'] . '</strike></b></div>'; } @@ -159,18 +159,18 @@ class Lockview extends \Zotlabs\Web\Controller { $r = q("SELECT gname FROM groups WHERE hash IN ( " . implode(', ', $deny_groups) . " )"); if($r) foreach($r as $rr) - $l[] = '<li><b><strike>' . $rr['gname'] . '</strike></b></li>'; + $l[] = '<div class="dropdown-item"><b><strike>' . $rr['gname'] . '</strike></b></div>'; } if(count($deny_users)) { $r = q("SELECT xchan_name FROM xchan WHERE xchan_hash IN ( " . implode(', ', $deny_users) . " )"); if($r) foreach($r as $rr) - $l[] = '<li><strike>' . $rr['xchan_name'] . '</strike></li>'; + $l[] = '<div class="dropdown-item"><strike>' . $rr['xchan_name'] . '</strike></div>'; if($atokens) { foreach($atokens as $at) { if(in_array("'" . $at['xchan_hash'] . "'",$deny_users)) { - $l[] = '<li><strike>' . $at['xchan_name'] . '</strike></li>'; + $l[] = '<div class="dropdown-item"><strike>' . $at['xchan_name'] . '</strike></div>'; } } } diff --git a/Zotlabs/Module/Mail.php b/Zotlabs/Module/Mail.php index 459ce5acf..d605a78a9 100644 --- a/Zotlabs/Module/Mail.php +++ b/Zotlabs/Module/Mail.php @@ -113,18 +113,18 @@ class Mail extends \Zotlabs\Web\Controller { if($preview) { $mail = [ - 'mailbox' => 'outbox', - 'id' => 0, - 'mid' => 'M0', - 'from_name' => $channel['xchan_name'], - 'from_url' => $channel['xchan_url'], - 'from_photo' => $channel['xchan_photo_s'], - 'subject' => zidify_links(smilies(bbcode($subject))), - 'body' => zidify_links(smilies(bbcode($body))), + 'mailbox' => 'outbox', + 'id' => 0, + 'mid' => 'M0', + 'from_name' => $channel['xchan_name'], + 'from_url' => $channel['xchan_url'], + 'from_photo' => $channel['xchan_photo_s'], + 'subject' => zidify_links(smilies(bbcode($subject))), + 'body' => zidify_links(smilies(bbcode($body))), 'attachments' => '', - 'can_recall' => false, + 'can_recall' => false, 'is_recalled' => '', - 'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c') + 'date' => datetime_convert('UTC',date_default_timezone_get(),$message['created'], 'c') ]; echo replace_macros(get_markup_template('mail_conv.tpl'), [ '$mail' => $mail ] ); @@ -178,6 +178,25 @@ class Mail extends \Zotlabs\Web\Controller { '$header' => t('Messages'), )); + if(argc() == 3 && intval(argv(1)) && argv(2) === 'download') { + + $r = q("select * from mail where id = %d and channel_id = %d", + intval(argv(1)), + intval(local_channel()) + ); + + if($r) { + + header('Content-type: ' . $r[0]['mail_mimetype']); + header('Content-disposition: attachment; filename="' . t('message') . '-' . $r[0]['id'] . '"' ); + $body = (($r[0]['mail_obscured']) ? base64url_decode(str_rot47($r[0]['body'])) : $r[0]['body']); + echo $body; + killme(); + } + + } + + if((argc() == 4) && (argv(2) === 'drop')) { if(! intval(argv(3))) return; @@ -296,7 +315,9 @@ class Mail extends \Zotlabs\Web\Controller { return $o; } - + + $direct_mid = 0; + switch(argv(1)) { case 'combined': $mailbox = 'combined'; @@ -309,12 +330,22 @@ class Mail extends \Zotlabs\Web\Controller { break; default: $mailbox = 'combined'; + + // notifications direct to mail/nn + + if(intval(argv(1))) + $direct_mid = intval(argv(1)); break; } + $last_message = private_messages_list(local_channel(), $mailbox, 0, 1); - + $mid = ((argc() > 2) && (intval(argv(2)))) ? argv(2) : $last_message[0]['id']; + + if($direct_mid) + $mid = $direct_mid; + $plaintext = true; @@ -358,6 +389,11 @@ class Mail extends \Zotlabs\Web\Controller { foreach($messages as $message) { $s = theme_attachments($message); + + if($message['mail_raw']) + $message['body'] = mail_prepare_binary([ 'id' => $message['id'] ]); + else + $message['body'] = zidify_links(smilies(bbcode($message['body']))); $mails[] = array( 'mailbox' => $mailbox, @@ -370,7 +406,7 @@ class Mail extends \Zotlabs\Web\Controller { 'to_url' => chanlink_hash($message['to_xchan']), 'to_photo' => $message['to']['xchan_photo_s'], 'subject' => $message['title'], - 'body' => zidify_links(smilies(bbcode($message['body']))), + 'body' => $message['body'], 'attachments' => $s, 'delete' => t('Delete message'), 'dreport' => t('Delivery report'), diff --git a/Zotlabs/Module/Manage.php b/Zotlabs/Module/Manage.php index 3b7b3c3dd..e541ee077 100644 --- a/Zotlabs/Module/Manage.php +++ b/Zotlabs/Module/Manage.php @@ -46,107 +46,111 @@ class Manage extends \Zotlabs\Web\Controller { $channels = null; - if(local_channel()) { - $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ", - intval(get_account_id()) - ); + $r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ", + intval(get_account_id()) + ); - $account = \App::get_account(); + $account = \App::get_account(); - if($r && count($r)) { - $channels = $r; - for($x = 0; $x < count($channels); $x ++) { - $channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']); - $channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : ''); - $channels[$x]['default_links'] = '1'; + if($r && count($r)) { + $channels = $r; + for($x = 0; $x < count($channels); $x ++) { + $channels[$x]['link'] = 'manage/' . intval($channels[$x]['channel_id']); + $channels[$x]['default'] = (($channels[$x]['channel_id'] == $account['account_default_channel']) ? "1" : ''); + $channels[$x]['default_links'] = '1'; - $c = q("SELECT id, item_wall FROM item - WHERE item_unseen = 1 and uid = %d " . item_normal(), - intval($channels[$x]['channel_id']) - ); + $c = q("SELECT id, item_wall FROM item + WHERE item_unseen = 1 and uid = %d " . item_normal(), + intval($channels[$x]['channel_id']) + ); - if($c) { - foreach ($c as $it) { - if(intval($it['item_wall'])) - $channels[$x]['home'] ++; - else - $channels[$x]['network'] ++; - } + if($c) { + foreach ($c as $it) { + if(intval($it['item_wall'])) + $channels[$x]['home'] ++; + else + $channels[$x]['network'] ++; } + } - $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ", - intval($channels[$x]['channel_id']) - ); + $intr = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash where abook_channel = %d and abook_pending = 1 and abook_self = 0 and abook_ignored = 0 and xchan_deleted = 0 and xchan_orphan = 0 ", + intval($channels[$x]['channel_id']) + ); - if($intr) - $channels[$x]['intros'] = intval($intr[0]['total']); + if($intr) + $channels[$x]['intros'] = intval($intr[0]['total']); - $mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ", - intval($channels[$x]['channel_id']), - dbesc($channels[$x]['channel_hash']) - ); + $mails = q("SELECT count(id) as total from mail WHERE channel_id = %d AND mail_seen = 0 and from_xchan != '%s' ", + intval($channels[$x]['channel_id']), + dbesc($channels[$x]['channel_hash']) + ); - if($mails) - $channels[$x]['mail'] = intval($mails[0]['total']); + if($mails) + $channels[$x]['mail'] = intval($mails[0]['total']); - $events = q("SELECT etype, dtstart, adjust FROM event - WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0 - ORDER BY dtstart ASC ", - intval($channels[$x]['channel_id']), - dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')), - dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) - ); - - if($events) { - $channels[$x]['all_events'] = count($events); - - if($channels[$x]['all_events']) { - $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d'); - foreach($events as $e) { - $bd = false; - if($e['etype'] === 'birthday') { - $channels[$x]['birthdays'] ++; - $bd = true; - } - else { - $channels[$x]['events'] ++; - } - if(datetime_convert('UTC', ((intval($e['adjust'])) ? date_default_timezone_get() : 'UTC'), $e['dtstart'], 'Y-m-d') === $str_now) { - $channels[$x]['all_events_today'] ++; - if($bd) - $channels[$x]['birthdays_today'] ++; - else - $channels[$x]['events_today'] ++; - } + $events = q("SELECT etype, dtstart, adjust FROM event + WHERE event.uid = %d AND dtstart < '%s' AND dtstart > '%s' and dismissed = 0 + ORDER BY dtstart ASC ", + intval($channels[$x]['channel_id']), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now + 7 days')), + dbesc(datetime_convert('UTC', date_default_timezone_get(), 'now - 1 days')) + ); + + if($events) { + $channels[$x]['all_events'] = count($events); + + if($channels[$x]['all_events']) { + $str_now = datetime_convert('UTC', date_default_timezone_get(), 'now', 'Y-m-d'); + foreach($events as $e) { + $bd = false; + if($e['etype'] === 'birthday') { + $channels[$x]['birthdays'] ++; + $bd = true; + } + else { + $channels[$x]['events'] ++; + } + if(datetime_convert('UTC', ((intval($e['adjust'])) ? date_default_timezone_get() : 'UTC'), $e['dtstart'], 'Y-m-d') === $str_now) { + $channels[$x]['all_events_today'] ++; + if($bd) + $channels[$x]['birthdays_today'] ++; + else + $channels[$x]['events_today'] ++; } } } } } - - $r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0", - intval(get_account_id()) - ); - $limit = account_service_class_fetch(get_account_id(),'total_identities'); - if($limit !== false) { - $channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit); - } - else { - $channel_usage_message = ''; - } + + } + + $r = q("select count(channel_id) as total from channel where channel_account_id = %d and channel_removed = 0", + intval(get_account_id()) + ); + $limit = account_service_class_fetch(get_account_id(),'total_identities'); + if($limit !== false) { + $channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit); } + else { + $channel_usage_message = ''; + } + $create = array( 'new_channel', t('Create a new channel'), t('Create New')); - $delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where - abook_channel = %d and abook_xchan in ( select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'delegate' and v = '1' )", - intval(local_channel()), - intval(local_channel()) - ); + $delegates = null; + + if(local_channel()) { + $delegates = q("select * from abook left join xchan on abook_xchan = xchan_hash where + abook_channel = %d and abook_xchan in ( select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'delegate' and v = '1' )", + intval(local_channel()), + intval(local_channel()) + ); + } if($delegates) { for($x = 0; $x < count($delegates); $x ++) { diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 8263420b6..1c7c70019 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -118,8 +118,8 @@ class Network extends \Zotlabs\Web\Controller { $cmax = ((x($_GET,'cmax')) ? intval($_GET['cmax']) : 99); $firehose = ((x($_GET,'fh')) ? intval($_GET['fh']) : 0); $file = ((x($_GET,'file')) ? $_GET['file'] : ''); - - + $xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : ''); + $deftag = ''; if(x($_GET,'search') || x($_GET,'file')) @@ -257,6 +257,26 @@ class Network extends \Zotlabs\Web\Controller { goaway(z_root() . '/network'); } } + elseif($xchan) { + $r = q("select * from xchan where xchan_hash = '%s'", + dbesc($xchan) + ); + if($r) { + $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval(local_channel()) . " AND ( author_xchan = '" . dbesc($xchan) . "' or owner_xchan = '" . dbesc($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 channel.') . EOL); + goaway(z_root() . '/network'); + } + + } if(x($category)) { $sql_extra .= protect_sprintf(term_query('item', $category, TERM_CATEGORY)); @@ -302,6 +322,7 @@ class Network extends \Zotlabs\Web\Controller { '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), '$search' => (($search) ? $search : ''), + '$xchan' => $xchan, '$order' => $order, '$file' => $file, '$cats' => $category, diff --git a/Zotlabs/Module/Notifications.php b/Zotlabs/Module/Notifications.php index e0313dd8b..652648701 100644 --- a/Zotlabs/Module/Notifications.php +++ b/Zotlabs/Module/Notifications.php @@ -40,7 +40,7 @@ class Notifications extends \Zotlabs\Web\Controller { $o .= replace_macros(get_markup_template('notifications.tpl'),array( '$notif_header' => t('System Notifications'), - '$notif_link_mark_seen' => t('Mark all system notifications seen'), + '$notif_link_mark_seen' => t('Mark all seen'), '$notif_content' => $notif_content, '$notifications_available' => $notifications_available, )); diff --git a/Zotlabs/Module/Ofeed.php b/Zotlabs/Module/Ofeed.php new file mode 100644 index 000000000..2b7acff99 --- /dev/null +++ b/Zotlabs/Module/Ofeed.php @@ -0,0 +1,48 @@ +<?php + +namespace Zotlabs\Module; + +/* Ofeed: Broken feed for software which requires broken feeds */ + +require_once('include/items.php'); + +class Ofeed extends \Zotlabs\Web\Controller { + + function init() { + + $params = []; + + $params['begin'] = ((x($_REQUEST,'date_begin')) ? $_REQUEST['date_begin'] : NULL_DATE); + $params['end'] = ((x($_REQUEST,'date_end')) ? $_REQUEST['date_end'] : ''); + $params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml'); + $params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0); + $params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0); + $params['start'] = ((x($params,'start')) ? intval($params['start']) : 0); + $params['records'] = ((x($params,'records')) ? intval($params['records']) : 40); + $params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc'); + $params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : ''); + $params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 1); + + + if(argc() > 1) { + + if(observer_prohibited(true)) { + killme(); + } + + $channel = channelx_by_nick(argv(1)); + if(! $channel) { + killme(); + } + + + logger('public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['channel_address']); + + echo get_public_feed($channel,$params); + + killme(); + } + + } + +} diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php index 256a51e71..dc4ae670e 100644 --- a/Zotlabs/Module/Photo.php +++ b/Zotlabs/Module/Photo.php @@ -127,7 +127,6 @@ class Photo extends \Zotlabs\Web\Controller { } } - $r = q("SELECT uid FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", dbesc($photo), intval($resolution) @@ -150,12 +149,14 @@ class Photo extends \Zotlabs\Web\Controller { $channel = channelx_by_n($r[0]['uid']); // Now we'll see if we can access the photo - $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale = %d $sql_extra LIMIT 1", dbesc($photo), intval($resolution) ); - + + if($r && $r[0]['photo_usage'] == PHOTO_COVER) + $allowed = 1; + $d = [ 'imgscale' => $resolution, 'resource_id' => $photo, 'photo' => $r, 'allowed' => $allowed ]; call_hooks('get_photo',$d); diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php index 582174d0e..d993c481e 100644 --- a/Zotlabs/Module/Photos.php +++ b/Zotlabs/Module/Photos.php @@ -15,13 +15,10 @@ class Photos extends \Zotlabs\Web\Controller { function init() { - if(observer_prohibited()) { return; } - $o = ''; - if(argc() > 1) { $nick = argv(1); @@ -54,7 +51,6 @@ class Photos extends \Zotlabs\Web\Controller { logger('mod-photos: photos_post: begin' , LOGGER_DEBUG); - logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA); logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA); @@ -92,14 +88,9 @@ class Photos extends \Zotlabs\Web\Controller { if((argc() > 3) && (argv(2) === 'album')) { - $album = hex2bin(argv(3)); - - if($album === t('Profile Photos')) { - // not allowed - goaway(z_root() . '/' . $_SESSION['photo_return']); - } - - if(! photos_album_exists($page_owner_uid,$album)) { + $album = argv(3); + + if(! photos_album_exists($page_owner_uid, get_observer_hash(), $album)) { notice( t('Album not found.') . EOL); goaway(z_root() . '/' . $_SESSION['photo_return']); } @@ -121,7 +112,7 @@ class Photos extends \Zotlabs\Web\Controller { $folder_hash = ''; - $r = q("select * from attach where is_dir = 1 and uid = %d and filename = '%s'", + $r = q("select * from attach where is_dir = 1 and uid = %d and hash = '%s'", intval($page_owner_uid), dbesc($album) ); @@ -129,14 +120,7 @@ class Photos extends \Zotlabs\Web\Controller { notice( t('Album not found.') . EOL); return; } - if(count($r) > 1) { - notice( t('Multiple storage folders exist with this album name, but within different directories. Please remove the desired folder or folders using the Files manager') . EOL); - return; - } - else { - $folder_hash = $r[0]['hash']; - } - + $folder_hash = $r[0]['hash']; $res = array(); @@ -468,7 +452,7 @@ class Photos extends \Zotlabs\Web\Controller { * default post action - upload a photo */ - $channel = \App::$data['channel']; + $channel = \App::$data['channel']; $observer = \App::$data['observer']; $_REQUEST['source'] = 'photos'; @@ -485,12 +469,10 @@ class Photos extends \Zotlabs\Web\Controller { if(! $r['success']) { notice($r['message'] . EOL); + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); } - - if($_REQUEST['newalbum']) - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($_REQUEST['newalbum'])); - else - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex(datetime_convert('UTC',date_default_timezone_get(),'now', 'Y'))); + + goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $r['data']['folder']); } @@ -569,7 +551,9 @@ class Photos extends \Zotlabs\Web\Controller { return; } - $sql_extra = permissions_sql($owner_uid); + $sql_item = item_permissions_sql($owner_uid,get_observer_hash()); + $sql_extra = permissions_sql($owner_uid,get_observer_hash(),'photo'); + $sql_attach = permissions_sql($owner_uid,get_observer_hash(),'attach'); $o = ""; @@ -579,7 +563,7 @@ class Photos extends \Zotlabs\Web\Controller { // tabs $_is_owner = (local_channel() && (local_channel() == $owner_uid)); - $o .= profile_tabs($a,$_is_owner, \App::$data['channel']['channel_address']); + //$o .= profile_tabs($a,$_is_owner, \App::$data['channel']['channel_address']); /** * Display upload form @@ -628,8 +612,14 @@ class Photos extends \Zotlabs\Web\Controller { if(! $aclselect) { $aclselect = '<input id="group_allow" type="hidden" name="allow_gid[]" value="" /><input id="contact_allow" type="hidden" name="allow_cid[]" value="" /><input id="group_deny" type="hidden" name="deny_gid[]" value="" /><input id="contact_deny" type="hidden" name="deny_cid[]" value="" />'; } - - $selname = (($datum) ? hex2bin($datum) : ''); + + $selname = ''; + + if($datum) { + $h = attach_by_hash_nodata($datum,get_observer_hash()); + $selname = $h['data']['display_path']; + } + $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); @@ -680,29 +670,13 @@ class Photos extends \Zotlabs\Web\Controller { if($datatype === 'album') { - if(strlen($datum)) { - if((strlen($datum) & 1) || (! ctype_xdigit($datum))) { - notice( t('Album name could not be decoded') . EOL); - logger('mod_photos: illegal album encoding: ' . $datum); - $datum = ''; - goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); - } - } - - $album = (($datum) ? hex2bin($datum) : ''); - \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n"; - //check if the album exists and if we have perms - $r = q("SELECT album FROM photo WHERE uid = %d AND album = '%s' and is_nsfw = %d $sql_extra LIMIT 1", - intval($owner_uid), - dbesc($album), - intval($unsafe) - ); - - if($r) { + if($x = photos_album_exists($owner_uid, get_observer_hash(), $datum)) { \App::set_pager_itemspage(60); - } else { + $album = $x['display_path']; + } + else { goaway(z_root() . '/photos/' . \App::$data['channel']['channel_address']); } @@ -712,26 +686,26 @@ class Photos extends \Zotlabs\Web\Controller { $order = 'DESC'; $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN - (SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph + (SELECT resource_id, max(imgscale) imgscale FROM photo left join attach on folder = '%s' and photo.resource_id = attach.hash WHERE attach.uid = %d AND imgscale <= 4 AND photo_usage IN ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id) ph ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale) ORDER BY created $order LIMIT %d OFFSET %d", + dbesc($datum), intval($owner_uid), - dbesc($album), intval(PHOTO_NORMAL), intval(PHOTO_PROFILE), intval($unsafe), intval(\App::$pager['itemspage']), intval(\App::$pager['start']) ); - - //edit album name + + // edit album name $album_edit = null; - if(($album !== t('Profile Photos')) && ($album !== 'Profile Photos') && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) { - if($can_post) { - $album_e = $album; - $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); + + if($can_post) { + $album_e = $album; + $albums = ((array_key_exists('albums', \App::$data)) ? \App::$data['albums'] : photos_albums_list(\App::$data['channel'],\App::$data['observer'])); - // @fixme - syncronise actions with DAV + // @fixme - syncronise actions with DAV // $edit_tpl = get_markup_template('album_edit.tpl'); // $album_edit = replace_macros($edit_tpl,array( @@ -745,13 +719,12 @@ class Photos extends \Zotlabs\Web\Controller { // '$dropsubmit' => t('Delete Album') // )); - } } if($_GET['order'] === 'posted') - $order = array(t('Show Newest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($album)); + $order = array(t('Show Newest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $datum); else - $order = array(t('Show Oldest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($album) . '?f=&order=posted'); + $order = array(t('Show Oldest First'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $datum . '?f=&order=posted'); $photos = array(); if(count($r)) { @@ -805,10 +778,10 @@ class Photos extends \Zotlabs\Web\Controller { $o .= replace_macros($tpl, array( '$photos' => $photos, '$album' => $album, - '$album_id' => bin2hex($album), + '$album_id' => $datum, '$album_edit' => array(t('Edit Album'), $album_edit), '$can_post' => $can_post, - '$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . bin2hex($album)), + '$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/upload/' . $datum), '$order' => $order, '$upload_form' => $upload_form, '$usage' => $usage_message @@ -822,8 +795,6 @@ class Photos extends \Zotlabs\Web\Controller { killme(); } - // $o .= paginate($a); - return $o; } @@ -836,6 +807,11 @@ class Photos extends \Zotlabs\Web\Controller { \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n"; + $x = q("select folder from attach where hash = '%s' and uid = %d $sql_attach limit 1", + dbesc($datum), + intval($owner_uid) + ); + // fetch image, item containing image, then comments $ph = q("SELECT id,aid,uid,xchan,resource_id,created,edited,title,description,album,filename,mimetype,height,width,filesize,imgscale,photo_usage,is_nsfw,allow_cid,allow_gid,deny_cid,deny_gid FROM photo WHERE uid = %d AND resource_id = '%s' @@ -844,7 +820,7 @@ class Photos extends \Zotlabs\Web\Controller { dbesc($datum) ); - if(! $ph) { + if(! ($ph && $x)) { /* Check again - this time without specifying permissions */ @@ -869,16 +845,16 @@ class Photos extends \Zotlabs\Web\Controller { else $order = 'DESC'; - - $prvnxt = q("SELECT resource_id FROM photo WHERE album = '%s' AND uid = %d AND imgscale = 0 - $sql_extra ORDER BY created $order ", - dbesc($ph[0]['album']), + + $prvnxt = q("SELECT hash FROM attach WHERE folder = '%s' AND uid = %d AND is_photo = 1 + $sql_attach ORDER BY created $order ", + dbesc($x[0]['folder']), intval($owner_uid) ); - + if(count($prvnxt)) { for($z = 0; $z < count($prvnxt); $z++) { - if($prvnxt[$z]['resource_id'] == $ph[0]['resource_id']) { + if($prvnxt[$z]['hash'] == $ph[0]['resource_id']) { $prv = $z - 1; $nxt = $z + 1; if($prv < 0) @@ -889,8 +865,8 @@ class Photos extends \Zotlabs\Web\Controller { } } - $prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''); - $nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['resource_id'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''); + $prevlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$prv]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''); + $nextlink = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $prvnxt[$nxt]['hash'] . (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''); } @@ -907,7 +883,7 @@ class Photos extends \Zotlabs\Web\Controller { } } - $album_link = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($ph[0]['album']); + $album_link = z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . $x[0]['folder']; $tools = Null; $lock = Null; @@ -947,7 +923,7 @@ class Photos extends \Zotlabs\Web\Controller { // Do we have an item for this photo? $linked_items = q("SELECT * FROM item WHERE resource_id = '%s' and resource_type = 'photo' - $sql_extra LIMIT 1", + $sql_item LIMIT 1", dbesc($datum) ); @@ -962,7 +938,7 @@ class Photos extends \Zotlabs\Web\Controller { $item_normal = item_normal(); $r = q("select * from item where parent_mid = '%s' - $item_normal and uid = %d $sql_extra ", + $item_normal and uid = %d $sql_item ", dbesc($link_item['mid']), intval($link_item['uid']) @@ -1008,13 +984,6 @@ class Photos extends \Zotlabs\Web\Controller { $edit = null; if($can_post) { - $m = q("select folder from attach where hash = '%s' and uid = %d limit 1", - dbesc($ph[0]['resource_id']), - intval($ph[0]['uid']) - ); - if($m) - $album_hash = $m[0]['folder']; - $album_e = $ph[0]['album']; $caption_e = $ph[0]['description']; $aclselect_e = (($_is_owner) ? populate_acl($ph[0], true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_storage')) : ''); @@ -1024,35 +993,35 @@ class Photos extends \Zotlabs\Web\Controller { $folder_list = attach_folder_select_list($ph[0]['uid']); - $edit = array( + $edit = [ 'edit' => t('Edit photo'), 'id' => $link_item['id'], - 'rotatecw' => t('Rotate CW (right)'), - 'rotateccw' => t('Rotate CCW (left)'), - 'albums' => $albums['albums'], - 'album' => $album_e, - 'album_select' => [ 'move_to_album', t('Move photo to album'), $album_hash, '', $folder_list ], - 'newalbum_label' => t('Enter a new album name'), + 'rotatecw' => t('Rotate CW (right)'), + 'rotateccw' => t('Rotate CCW (left)'), + 'albums' => $albums['albums'], + 'album' => $album_e, + 'album_select' => [ 'move_to_album', t('Move photo to album'), $x[0]['folder'], '', $folder_list ], + 'newalbum_label' => t('Enter a new album name'), 'newalbum_placeholder' => t('or select an existing one (doubleclick)'), - 'nickname' => \App::$data['channel']['channel_address'], - 'resource_id' => $ph[0]['resource_id'], - 'capt_label' => t('Caption'), - 'caption' => $caption_e, - 'tag_label' => t('Add a Tag'), - 'permissions' => t('Permissions'), - 'aclselect' => $aclselect_e, - 'allow_cid' => acl2json($ph[0]['allow_cid']), - 'allow_gid' => acl2json($ph[0]['allow_gid']), - 'deny_cid' => acl2json($ph[0]['deny_cid']), - 'deny_gid' => acl2json($ph[0]['deny_gid']), - 'lockstate' => $lockstate[0], - 'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'), - 'item_id' => ((count($linked_items)) ? $link_item['id'] : 0), - 'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'), - 'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''), - 'submit' => t('Submit'), - 'delete' => t('Delete Photo') - ); + 'nickname' => \App::$data['channel']['channel_address'], + 'resource_id' => $ph[0]['resource_id'], + 'capt_label' => t('Caption'), + 'caption' => $caption_e, + 'tag_label' => t('Add a Tag'), + 'permissions' => t('Permissions'), + 'aclselect' => $aclselect_e, + 'allow_cid' => acl2json($ph[0]['allow_cid']), + 'allow_gid' => acl2json($ph[0]['allow_gid']), + 'deny_cid' => acl2json($ph[0]['deny_cid']), + 'deny_gid' => acl2json($ph[0]['deny_gid']), + 'lockstate' => $lockstate[0], + 'help_tags' => t('Example: @bob, @Barbara_Jensen, @jim@example.com'), + 'item_id' => ((count($linked_items)) ? $link_item['id'] : 0), + 'adult_enabled' => feature_enabled($owner_uid,'adult_photo_flagging'), + 'adult' => array('adult',t('Flag as adult in album view'), intval($ph[0]['is_nsfw']),''), + 'submit' => t('Submit'), + 'delete' => t('Delete Photo') + ]; } if(count($linked_items)) { @@ -1066,13 +1035,13 @@ class Photos extends \Zotlabs\Web\Controller { $likebuttons = ''; if($can_post || $can_comment) { - $likebuttons = array( - 'id' => $link_item['id'], + $likebuttons = [ + 'id' => $link_item['id'], 'likethis' => t("I like this \x28toggle\x29"), - 'nolike' => t("I don't like this \x28toggle\x29"), - 'share' => t('Share'), - 'wait' => t('Please wait') - ); + 'nolike' => t("I don't like this \x28toggle\x29"), + 'share' => t('Share'), + 'wait' => t('Please wait') + ]; } $comments = ''; @@ -1277,25 +1246,13 @@ class Photos extends \Zotlabs\Web\Controller { \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$cmd) . '" title="oembed" />' . "\r\n"; - /* - $r = q("SELECT resource_id, max(imgscale) AS imgscale FROM photo WHERE uid = %d - and photo_usage in ( %d, %d ) and is_nsfw = %d $sql_extra GROUP BY resource_id", - intval(\App::$data['channel']['channel_id']), - intval(PHOTO_NORMAL), - intval(PHOTO_PROFILE), - intval($unsafe) - ); - if($r) { - \App::set_pager_total(count($r)); - \App::set_pager_itemspage(60); - } - */ \App::set_pager_itemspage(60); - $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.album, p.imgscale, p.created FROM photo p + $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.album, p.imgscale, p.created, p.display_path + FROM photo p INNER JOIN ( SELECT resource_id, max(imgscale) imgscale FROM photo - WHERE uid = %d AND photo_usage IN ( %d, %d ) + WHERE photo.uid = %d AND photo_usage IN ( %d, %d ) AND is_nsfw = %d $sql_extra group by resource_id ) ph ON (p.resource_id = ph.resource_id and p.imgscale = ph.imgscale) ORDER by p.created DESC LIMIT %d OFFSET %d", @@ -1313,21 +1270,19 @@ class Photos extends \Zotlabs\Web\Controller { if($r) { $twist = 'rotright'; foreach($r as $rr) { + + if(! attach_can_view_folder(\App::$data['channel']['channel_id'],get_observer_hash(),$rr['resource_id'])) + continue; + if($twist == 'rotright') $twist = 'rotleft'; else $twist = 'rotright'; $ext = $phototypes[$rr['mimetype']]; - if(\App::get_template_engine() === 'internal') { - $alt_e = template_escape($rr['filename']); - $name_e = template_escape($rr['album']); - } - else { - $alt_e = $rr['filename']; - $name_e = $rr['album']; - } - + $alt_e = $rr['filename']; + $name_e = dirname($rr['display_path']); + $photos[] = array( 'id' => $rr['id'], 'twist' => ' ' . $twist . rand(2,4), @@ -1336,9 +1291,7 @@ class Photos extends \Zotlabs\Web\Controller { 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . ((($rr['imgscale']) == 6) ? 4 : $rr['imgscale']) . '.' . $ext, 'alt' => $alt_e, 'album' => array( - 'link' => z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/album/' . bin2hex($rr['album']), 'name' => $name_e, - 'alt' => t('View Album'), ), ); diff --git a/Zotlabs/Module/Profile.php b/Zotlabs/Module/Profile.php index fda88da52..ab349b05d 100644 --- a/Zotlabs/Module/Profile.php +++ b/Zotlabs/Module/Profile.php @@ -101,7 +101,7 @@ class Profile extends \Zotlabs\Web\Controller { return; } - $o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']); + //$o .= profile_tabs($a, $is_owner, \App::$profile['channel_address']); \App::$page['htmlhead'] .= "\r\n" . '<link rel="alternate" type="application/json+oembed" href="' . z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string) . '" title="oembed" />' . "\r\n"; diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php index 438580917..e8f0e5186 100644 --- a/Zotlabs/Module/Profile_photo.php +++ b/Zotlabs/Module/Profile_photo.php @@ -108,11 +108,13 @@ class Profile_photo extends \Zotlabs\Web\Controller { $aid = get_account_id(); $p = [ - 'aid' => $aid, - 'uid' => local_channel(), - 'resource_id' => $base_image['resource_id'], - 'filename' => $base_image['filename'], - 'album' => t('Profile Photos') + 'aid' => $aid, + 'uid' => local_channel(), + 'resource_id' => $base_image['resource_id'], + 'filename' => $base_image['filename'], + 'album' => t('Profile Photos'), + 'os_path' => $base_image['os_path'], + 'display_path' => $base_image['display_path'] ]; $p['imgscale'] = PHOTO_RES_PROFILE_300; diff --git a/Zotlabs/Module/Profiles.php b/Zotlabs/Module/Profiles.php index 32e888f14..f6e8b11ed 100644 --- a/Zotlabs/Module/Profiles.php +++ b/Zotlabs/Module/Profiles.php @@ -317,8 +317,10 @@ class Profiles extends \Zotlabs\Web\Controller { $hide_friends = ((intval($_POST['hide_friends'])) ? 1: 0); +// start fresh and create a new vcard. TODO: preserve the original guid or whatever else needs saving +// $orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null); - $orig_vcard = (($orig[0]['profile_vcard']) ? \Sabre\VObject\Reader::read($orig[0]['profile_vcard']) : null); + $orig_vcard = null; $channel = \App::get_channel(); @@ -330,13 +332,7 @@ class Profiles extends \Zotlabs\Web\Controller { 'photo' => $channel['xchan_photo_l'], 'adr' => [], 'adr_type' => [ $default_vcard_cat ], - 'tel' => [], - 'tel_type' => [ $default_vcard_cat ], - 'email' => [], - 'email_type' => [ $default_vcard_cat ], - 'impp' => [], - 'impp_type' => [ $default_vcard_cat ], - 'url' => [], + 'url' => [ $homepage ], 'url_type' => [ $default_vcard_cat ] ]; @@ -350,9 +346,12 @@ class Profiles extends \Zotlabs\Web\Controller { 6 => $country_name ]; - $profile_vcard = update_vcard($defcard,$orig_vcard); + $orig_vcard = \Sabre\VObject\Reader::read($profile_vcard); + + $profile_vcard = update_vcard($_REQUEST,$orig_vcard); + require_once('include/text.php'); linkify_tags($a, $likes, local_channel()); @@ -700,6 +699,10 @@ class Profiles extends \Zotlabs\Web\Controller { } //logger('extra_fields: ' . print_r($extra_fields,true)); + + $vc = $r[0]['profile_vcard']; + $vctmp = (($vc) ? \Sabre\VObject\Reader::read($vc) : null); + $vcard = (($vctmp) ? get_vcard_array($vctmp,$r[0]['id']) : [] ); $f = get_config('system','birthday_input_format'); if(! $f) @@ -717,6 +720,7 @@ class Profiles extends \Zotlabs\Web\Controller { . get_form_security_token("profile_drop"), '$fields' => $fields, + '$vcard' => $vcard, '$guid' => $r[0]['profile_guid'], '$banner' => t('Edit Profile Details'), '$submit' => t('Submit'), @@ -776,11 +780,28 @@ class Profiles extends \Zotlabs\Web\Controller { '$film' => array('film', t('Film/Dance/Culture/Entertainment'), $r[0]['film']), '$interest' => array('interest', t('Hobbies/Interests'), $r[0]['interest']), '$romance' => array('romance',t('Love/Romance'), $r[0]['romance']), - '$work' => array('work', t('Work/Employment'), $r[0]['employment']), + '$employ' => array('work', t('Work/Employment'), $r[0]['employment']), '$education' => array('education', t('School/Education'), $r[0]['education']), '$contact' => array('contact', t('Contact information and social networks'), $r[0]['contact']), '$channels' => array('channels', t('My other channels'), $r[0]['channels']), '$extra_fields' => $extra_fields, + '$comms' => t('Communications'), + '$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'), )); $arr = array('profile' => $r[0], 'entry' => $o); diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 6c4d479d4..46210abb1 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -57,6 +57,7 @@ class Pubstream extends \Zotlabs\Web\Controller { '$static' => $static, '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), '$search' => '', + '$xchan' => '', '$order' => 'comment', '$file' => '', '$cats' => '', diff --git a/Zotlabs/Module/Search.php b/Zotlabs/Module/Search.php index 89eaa4ffa..aacdc88e7 100644 --- a/Zotlabs/Module/Search.php +++ b/Zotlabs/Module/Search.php @@ -130,6 +130,7 @@ class Search extends \Zotlabs\Web\Controller { '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), '$search' => (($tag) ? urlencode('#') : '') . $search, + '$xchan' => '', '$order' => '', '$file' => '', '$cats' => '', diff --git a/Zotlabs/Module/Settings/Channel.php b/Zotlabs/Module/Settings/Channel.php index 5b9cfdaca..56a7d0d8e 100644 --- a/Zotlabs/Module/Settings/Channel.php +++ b/Zotlabs/Module/Settings/Channel.php @@ -277,8 +277,8 @@ class Channel { if($email_changed && \App::$config['system']['register_policy'] == REGISTER_VERIFY) { // FIXME - set to un-verified, blocked and redirect to logout - // Why? Are we verifying people or email addresses? - + // Q: Why? Are we verifying people or email addresses? + // A: the policy is to verify email addresses } goaway(z_root() . '/settings' ); @@ -575,7 +575,7 @@ class Channel { '$removeme' => t('Remove Channel'), '$removechannel' => t('Remove this channel.'), '$firefoxshare' => t('Firefox Share $Projectname provider'), - '$cal_first_day' => array('first_day', t('Start calendar week on monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no), + '$cal_first_day' => array('first_day', t('Start calendar week on Monday'), ((get_pconfig(local_channel(),'system','cal_first_day')) ? 1 : ''), '', $yes_no), )); call_hooks('settings_form',$o); diff --git a/Zotlabs/Module/Setup.php b/Zotlabs/Module/Setup.php index 9c688af01..d4c31fd4e 100644 --- a/Zotlabs/Module/Setup.php +++ b/Zotlabs/Module/Setup.php @@ -508,6 +508,7 @@ class Setup extends \Zotlabs\Web\Controller { $this->check_add($ck_funcs, t('PDO database PHP module'), true, true); $this->check_add($ck_funcs, t('mb_string PHP module'), true, true); $this->check_add($ck_funcs, t('xml PHP module'), true, true); + $this->check_add($ck_funcs, t('zip PHP module'), true, true); if(function_exists('apache_get_modules')){ if (! in_array('mod_rewrite', apache_get_modules())) { @@ -550,8 +551,12 @@ class Setup extends \Zotlabs\Web\Controller { $ck_funcs[4]['help'] = t('Error: mb_string PHP module required but not installed.'); } if(! extension_loaded('xml')) { + $ck_funcs[5]['status'] = false; + $ck_funcs[5]['help'] = t('Error: xml PHP module required for DAV but not installed.'); + } + if(! extension_loaded('zip')) { $ck_funcs[6]['status'] = false; - $ck_funcs[6]['help'] = t('Error: xml PHP module required for DAV but not installed.'); + $ck_funcs[6]['help'] = t('Error: zip PHP module required but not installed.'); } $checks = array_merge($checks, $ck_funcs); @@ -624,7 +629,6 @@ class Setup extends \Zotlabs\Web\Controller { * @param[out] array &$checks */ function check_htaccess(&$checks) { - $a = get_app(); $status = true; $help = ''; $ssl_error = false; @@ -718,7 +722,6 @@ class Setup extends \Zotlabs\Web\Controller { * @return string with parsed HTML */ function what_next() { - $a = get_app(); // install the standard theme set_config('system', 'allowed_themes', 'redbasic'); diff --git a/Zotlabs/Module/Sharedwithme.php b/Zotlabs/Module/Sharedwithme.php index 25bc7dba3..5d6d0f7da 100644 --- a/Zotlabs/Module/Sharedwithme.php +++ b/Zotlabs/Module/Sharedwithme.php @@ -92,7 +92,8 @@ class Sharedwithme extends \Zotlabs\Web\Controller { } - $o = profile_tabs($a, $is_owner, $channel['channel_address']); + //$o = profile_tabs($a, $is_owner, $channel['channel_address']); + $o = ''; $o .= replace_macros(get_markup_template('sharedwithme.tpl'), array( '$header' => t('Files: shared with me'), diff --git a/Zotlabs/Module/Suggest.php b/Zotlabs/Module/Suggest.php index 367308d90..2a69145ed 100644 --- a/Zotlabs/Module/Suggest.php +++ b/Zotlabs/Module/Suggest.php @@ -3,8 +3,6 @@ namespace Zotlabs\Module; require_once('include/socgraph.php'); require_once('include/contact_widgets.php'); -require_once('include/widgets.php'); - class Suggest extends \Zotlabs\Web\Controller { @@ -23,7 +21,7 @@ class Suggest extends \Zotlabs\Web\Controller { } - function get() { + function get() { $o = ''; if(! local_channel()) { diff --git a/Zotlabs/Module/Viewsrc.php b/Zotlabs/Module/Viewsrc.php index cb305efc6..54ab89e81 100644 --- a/Zotlabs/Module/Viewsrc.php +++ b/Zotlabs/Module/Viewsrc.php @@ -13,6 +13,7 @@ class Viewsrc extends \Zotlabs\Web\Controller { $item_id = ((argc() > 1) ? intval(argv(1)) : 0); $json = ((argc() > 2 && argv(2) === 'json') ? true : false); + $dload = ((argc() > 2 && argv(2) === 'download') ? true : false); if(! local_channel()) { notice( t('Permission denied.') . EOL); @@ -27,7 +28,7 @@ class Viewsrc extends \Zotlabs\Web\Controller { $item_normal = item_normal(); if(local_channel() && $item_id) { - $r = q("select id, item_flags, 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 from item where uid in (%d , %d) and id = %d $item_normal limit 1", intval(local_channel()), intval($sys['channel_id']), intval($item_id) @@ -35,7 +36,15 @@ class Viewsrc extends \Zotlabs\Web\Controller { if($r) { if(intval($r[0]['item_obscured'])) - $r[0]['body'] = crypto_unencapsulate(json_decode($r[0]['body'],true),get_config('system','prvkey')); + $dload = true; + + if($dload) { + header('Content-type: ' . $r[0]['mimetype']); + header('Content-disposition: attachment; filename="' . t('item') . '-' . $item_id . '"' ); + echo $r[0]['body']; + killme(); + } + $content = escape_tags($r[0]['body']); $o = (($json) ? json_encode($content) : str_replace("\n",'<br />',$content)); diff --git a/Zotlabs/Module/Webpages.php b/Zotlabs/Module/Webpages.php index 46b94f091..5e3091dfa 100644 --- a/Zotlabs/Module/Webpages.php +++ b/Zotlabs/Module/Webpages.php @@ -142,7 +142,8 @@ class Webpages extends \Zotlabs\Web\Controller { $is_owner = ($uid && $uid == $owner); - $o = profile_tabs($a, $is_owner, \App::$profile['channel_address']); + //$o = profile_tabs($a, $is_owner, \App::$profile['channel_address']); + $o = ''; $x = array( 'webpage' => ITEM_TYPE_WEBPAGE, @@ -693,7 +694,8 @@ class Webpages extends \Zotlabs\Web\Controller { } rrmdir($zip_folderpath); rrmdir($tmp_folderpath); // delete temporary files - + killme(); + break; default : break; diff --git a/Zotlabs/Module/Wfinger.php b/Zotlabs/Module/Wfinger.php index 04eed47c3..9623a676b 100644 --- a/Zotlabs/Module/Wfinger.php +++ b/Zotlabs/Module/Wfinger.php @@ -38,6 +38,9 @@ class Wfinger extends \Zotlabs\Web\Controller { $channel = str_replace('acct:','',$resource); if(strpos($channel,'@') !== false) { $host = substr($channel,strpos($channel,'@')+1); + + // If the webfinger address points off site, redirect to the correct site + if(strcasecmp($host,\App::get_hostname())) { goaway('https://' . $host . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=' . $zot : '')); } @@ -77,54 +80,60 @@ class Wfinger extends \Zotlabs\Web\Controller { } } - $result['aliases'] = array(); + $result['aliases'] = []; - $result['properties'] = array( - 'http://webfinger.net/ns/name' => $r[0]['channel_name'], + $result['properties'] = [ + 'http://webfinger.net/ns/name' => $r[0]['channel_name'], 'http://xmlns.com/foaf/0.1/name' => $r[0]['channel_name'] - ); + ]; foreach($aliases as $alias) if($alias != $resource) $result['aliases'][] = $alias; - $result['links'] = array( + $result['links'] = [ - array( - 'rel' => 'http://webfinger.net/rel/avatar', + [ + 'rel' => 'http://webfinger.net/rel/avatar', 'type' => $r[0]['xchan_photo_mimetype'], 'href' => $r[0]['xchan_photo_l'] - ), + ], - array( - 'rel' => 'http://webfinger.net/rel/profile-page', + [ + 'rel' => 'http://webfinger.net/rel/profile-page', 'href' => z_root() . '/profile/' . $r[0]['channel_address'], - ), + ], - array( - 'rel' => 'http://webfinger.net/rel/blog', + [ + 'rel' => 'http://schemas.google.com/g/2010#updates-from', + 'type' => 'application/atom+xml', + 'href' => z_root() . '/ofeed/' . $r[0]['channel_address'] + ], + + [ + 'rel' => 'http://webfinger.net/rel/blog', 'href' => z_root() . '/channel/' . $r[0]['channel_address'], - ), + ], - array( - 'rel' => 'http://ostatus.org/schema/1.0/subscribe', + [ + 'rel' => 'http://ostatus.org/schema/1.0/subscribe', 'template' => z_root() . '/follow/url={uri}', - ), + ], - array( - 'rel' => 'http://purl.org/zot/protocol', + [ + 'rel' => 'http://purl.org/zot/protocol', 'href' => z_root() . '/.well-known/zot-info' . '?address=' . $r[0]['xchan_addr'], - ), + ], - array( - 'rel' => 'magic-public-key', + [ + 'rel' => 'magic-public-key', 'href' => 'data:application/magic-public-key,' . salmon_key($r[0]['channel_pubkey']), - ) - ); + ] + ]; if($zot) { // get a zotinfo packet and return it with webfinger - $result['zot'] = zotinfo(array('address' => $r[0]['xchan_addr'])); + $result['zot'] = zotinfo( [ 'address' => $r[0]['xchan_addr'] ]); } } else { @@ -132,7 +141,7 @@ class Wfinger extends \Zotlabs\Web\Controller { killme(); } - $arr = array('channel' => $r[0], 'request' => $_REQUEST, 'result' => $result); + $arr = [ 'channel' => $r[0], 'request' => $_REQUEST, 'result' => $result ]; call_hooks('webfinger',$arr); json_return_and_die($arr['result'],'application/jrd+json'); diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php index 15806ffc3..a1e377e68 100644 --- a/Zotlabs/Module/Wiki.php +++ b/Zotlabs/Module/Wiki.php @@ -3,6 +3,7 @@ namespace Zotlabs\Module; use \Zotlabs\Lib as Zlib; +use \Michelf\MarkdownExtra; require_once('include/acl_selectors.php'); require_once('include/conversation.php'); @@ -106,7 +107,8 @@ class Wiki extends \Zotlabs\Web\Controller { } $is_owner = ((local_channel()) && (local_channel() == \App::$profile['profile_uid']) ? true : false); - $o = profile_tabs($a, $is_owner, \App::$profile['channel_address']); + //$o = profile_tabs($a, $is_owner, \App::$profile['channel_address']); + $o = ''; // Download a wiki /* @@ -234,16 +236,17 @@ class Wiki extends \Zotlabs\Web\Controller { $mimeType = $p['mimeType']; - $rawContent = htmlspecialchars_decode(json_decode($p['content']),ENT_COMPAT); + $sampleContent = (($mimeType == 'text/bbcode') ? '[h3]' . t('New page') . '[/h3]' : '### ' . t('New page')); + + $content = (($p['content'] == '') ? $sampleContent : $p['content']); - $content = ($p['content'] !== '' ? $rawContent : '"# New page\n"'); // Render the Markdown-formatted page content in HTML if($mimeType == 'text/bbcode') { $renderedContent = Zlib\NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))), argv(0) . '/' . argv(1) . '/' . $wikiUrlName); } else { - require_once('library/markdown.php'); - $html = Zlib\NativeWikiPage::generate_toc(zidify_text(purify_html(Markdown(Zlib\NativeWikiPage::bbcode($content))))); + $content = Zlib\MarkdownSoap::unescape($content); + $html = Zlib\NativeWikiPage::generate_toc(zidify_text(MarkdownExtra::defaultTransform(Zlib\NativeWikiPage::bbcode($content)))); $renderedContent = Zlib\NativeWikiPage::convert_links($html, argv(0) . '/' . argv(1) . '/' . $wikiUrlName); } $showPageControls = $wiki_editor; @@ -252,6 +255,7 @@ class Wiki extends \Zotlabs\Web\Controller { goaway('/' . argv(0) . '/' . argv(1) . '/' . $wikiUrlName . '/' . $pageUrlName); } + $wikiModalID = random_string(3); $wikiModal = replace_macros(get_markup_template('generic_modal.tpl'), array( @@ -327,9 +331,12 @@ class Wiki extends \Zotlabs\Web\Controller { $html = Zlib\NativeWikiPage::convert_links(zidify_links(smilies(bbcode($content))),$wikiURL); } else { - require_once('library/markdown.php'); - $content = Zlib\NativeWikiPage::bbcode($content); - $html = Zlib\NativeWikiPage::generate_toc(zidify_text(purify_html(Markdown($content)))); + $bb = Zlib\NativeWikiPage::bbcode($content); + $x = new ZLib\MarkdownSoap($bb); + $md = $x->clean(); + $md = ZLib\MarkdownSoap::unescape($md); + $html = MarkdownExtra::defaultTransform($md); + $html = Zlib\NativeWikiPage::generate_toc(zidify_text($html)); $html = Zlib\NativeWikiPage::convert_links($html,$wikiURL); } json_return_and_die(array('html' => $html, 'success' => true)); @@ -356,6 +363,14 @@ class Wiki extends \Zotlabs\Web\Controller { if($wiki['urlName'] === '') { notice( t('Error creating wiki. Invalid name.') . EOL); goaway('/wiki'); + return; //not reached + } + + $exists = Zlib\NativeWiki::exists_by_name($owner['channel_id'], $wiki['urlName']); + if($exists['id']) { + notice( t('A wiki with this name already exists.') . EOL); + goaway('/wiki'); + return; //not reached } // Get ACL for permissions @@ -454,7 +469,11 @@ class Wiki extends \Zotlabs\Web\Controller { json_return_and_die(array('pages' => null, 'message' => 'Permission denied.', 'success' => false)); } - $page_list_html = widget_wiki_pages(array( + // @FIXME - we shouldn't invoke this if it isn't in the PDL or has been over-ridden + + $x = new \Zotlabs\Widget\Wiki_pages(); + + $page_list_html = $x->widget(array( 'resource_id' => $resource_id, 'refresh' => true, 'channel' => argv(1))); @@ -512,7 +531,6 @@ class Wiki extends \Zotlabs\Web\Controller { $resource_id = $_POST['resource_id']; $pageUrlName = $_POST['name']; - // Determine if observer has permission to read content $perms = Zlib\NativeWiki::get_permissions($resource_id, intval($owner['channel_id']), $observer_hash); @@ -521,11 +539,12 @@ class Wiki extends \Zotlabs\Web\Controller { json_return_and_die(array('historyHTML' => '', 'message' => 'Permission denied.', 'success' => false)); } - $historyHTML = widget_wiki_page_history(array( + $historyHTML = \Zotlabs\Lib\NativeWikiPage::render_page_history(array( 'resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'permsWrite' => $perms['write'] )); + json_return_and_die(array('historyHTML' => $historyHTML, 'message' => '', 'success' => true)); } diff --git a/Zotlabs/Module/Xrd.php b/Zotlabs/Module/Xrd.php index 3ed19962b..7b36576e0 100644 --- a/Zotlabs/Module/Xrd.php +++ b/Zotlabs/Module/Xrd.php @@ -57,7 +57,7 @@ class Xrd extends \Zotlabs\Web\Controller { '$aliases' => $aliases, '$profile_url' => z_root() . '/channel/' . $r[0]['channel_address'], '$hcard_url' => z_root() . '/hcard/' . $r[0]['channel_address'], - '$atom' => z_root() . '/feed/' . $r[0]['channel_address'], + '$atom' => z_root() . '/ofeed/' . $r[0]['channel_address'], '$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'], diff --git a/Zotlabs/Module/Zotfeed.php b/Zotlabs/Module/Zotfeed.php index 6b505c890..381e3acb2 100644 --- a/Zotlabs/Module/Zotfeed.php +++ b/Zotlabs/Module/Zotfeed.php @@ -22,7 +22,8 @@ class Zotfeed extends \Zotlabs\Web\Controller { $observer = \App::get_observer(); - + logger('observer: ' . get_observer_hash(), LOGGER_DEBUG); + $channel_address = ((argc() > 1) ? argv(1) : ''); if($channel_address) { $r = q("select channel_id, channel_name from channel where channel_address = '%s' and channel_removed = 0 limit 1", diff --git a/Zotlabs/Render/Comanche.php b/Zotlabs/Render/Comanche.php index 5826063fd..beee9796e 100644 --- a/Zotlabs/Render/Comanche.php +++ b/Zotlabs/Render/Comanche.php @@ -4,8 +4,6 @@ namespace Zotlabs\Render; require_once('include/security.php'); require_once('include/menu.php'); -require_once('include/widgets.php'); - class Comanche { @@ -20,7 +18,49 @@ class Comanche { $s = str_replace($mtch[0], '', $s); } } - + + /* + * This section supports the "switch" statement of the form given by the following + * example. The [default][/default] block must be the last in the arbitrary + * list of cases. The first case that matches the switch variable is used + * and the rest are not evaluated. + * + * [switch observer.language] + * [case de] + * [block]german-content[/block] + * [/case] + * [case es] + * [block]spanish-content[/block] + * [/case] + * [default] + * [block]english-content[/block] + * [/default] + * [/switch] + */ + + $cnt = preg_match_all("/\[switch (.*?)\](.*?)\[default\](.*?)\[\/default\]\s*\[\/switch\]/ism", $s, $matches, PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $switch_done = 0; + $switch_var = $this->get_condition_var($mtch[1]); + $default = $mtch[3]; + $cases = array(); + $cntt = preg_match_all("/\[case (.*?)\](.*?)\[\/case\]/ism", $mtch[2], $cases, PREG_SET_ORDER); + if($cntt) { + foreach($cases as $case) { + if($case[1] === $switch_var) { + $switch_done = 1; + $s = str_replace($mtch[0], $case[2], $s); + break; + } + } + if($switch_done === 0) { + $s = str_replace($mtch[0], $default, $s); + } + } + } + } + $cnt = preg_match_all("/\[if (.*?)\](.*?)\[else\](.*?)\[\/if\]/ism", $s, $matches, PREG_SET_ORDER); if($cnt) { foreach($matches as $mtch) { @@ -410,6 +450,21 @@ class Comanche { } } + $clsname = ucfirst($name); + $nsname = "\\Zotlabs\\Widget\\" . $clsname; + + if(file_exists('Zotlabs/SiteWidget/' . $clsname . '.php')) + require_once('Zotlabs/SiteWidget/' . $clsname . '.php'); + elseif(file_exists('Zotlabs/Widget/' . $clsname . '.php')) + require_once('Zotlabs/Widget/' . $clsname . '.php'); + if(class_exists($nsname)) { + $x = new $nsname; + $f = 'widget'; + if(method_exists($x,$f)) { + return $x->$f($vars); + } + } + $func = 'widget_' . trim($name); if(! function_exists($func)) { diff --git a/Zotlabs/Storage/Browser.php b/Zotlabs/Storage/Browser.php index f527a6a44..7162161ef 100644 --- a/Zotlabs/Storage/Browser.php +++ b/Zotlabs/Storage/Browser.php @@ -84,7 +84,7 @@ class Browser extends DAV\Browser\Plugin { require_once('include/conversation.php'); require_once('include/text.php'); if ($this->auth->owner_nick) { - $html = profile_tabs(get_app(), (($is_owner) ? true : false), $this->auth->owner_nick); + $html = ''; } $files = $this->server->getPropertiesForPath($path, array( @@ -240,9 +240,11 @@ class Browser extends DAV\Browser\Plugin { '$nick' => $this->auth->getCurrentUser() )); - $a = get_app(); + + $a = false; + \App::$page['content'] = $html; - load_pdl($a); + load_pdl(); $current_theme = \Zotlabs\Render\Theme::current(); @@ -255,7 +257,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($a); + construct_page(); } /** @@ -322,12 +324,16 @@ class Browser extends DAV\Browser\Plugin { if(strpos($path,$special) === 0) $path = trim(substr($path,$count),'/'); + $info = t('Please use DAV to upload large (video, audio) files.<br>See <a class="zrl" href="help/member/member_guide#Cloud_Desktop_Clients">Cloud Desktop Clients</a>'); + + $output .= replace_macros(get_markup_template('cloud_actionspanel.tpl'), array( '$folder_header' => t('Create new folder'), '$folder_submit' => t('Create'), '$upload_header' => t('Upload file'), '$upload_submit' => t('Upload'), '$quota' => $quota, + '$info' => $info, '$channick' => $this->auth->owner_nick, '$aclselect' => $aclselect, '$allow_cid' => acl2json($channel_acl['allow_cid']), diff --git a/Zotlabs/Storage/Directory.php b/Zotlabs/Storage/Directory.php index 5d078b04e..0ed7a3c68 100644 --- a/Zotlabs/Storage/Directory.php +++ b/Zotlabs/Storage/Directory.php @@ -49,7 +49,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { * @param BasicAuth &$auth_plugin */ public function __construct($ext_path, &$auth_plugin) { -// $ext_path = urldecode($ext_path); + // $ext_path = urldecode($ext_path); logger('directory ' . $ext_path, LOGGER_DATA); $this->ext_path = $ext_path; // remove "/cloud" from the beginning of the path @@ -167,6 +167,14 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { intval($this->auth->owner_id) ); + $x = attach_syspaths($this->auth->owner_id,$this->folder_hash); + + $y = q("update attach set display_path = '%s where hash = '%s' and uid = %d", + dbesc($x['path']), + dbesc($this->folder_hash), + intval($this->auth->owner_id) + ); + $ch = channelx_by_n($this->auth->owner_id); if ($ch) { $sync = attach_export_data($ch, $this->folder_hash); @@ -260,14 +268,18 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { dbesc($f), dbesc(datetime_convert()), dbesc(datetime_convert()), - '', //TODO: use os_path - '', //TODO: use display_path + '', + '', dbesc($allow_cid), dbesc($allow_gid), dbesc($deny_cid), dbesc($deny_gid) ); + // fetch the actual storage paths + + $xpath = attach_syspaths($this->auth->owner_id, $hash); + // returns the number of bytes that were written to the file, or FALSE on failure $size = file_put_contents($f, $data); // delete attach entry if file_put_contents() failed @@ -281,15 +293,17 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { $edited = datetime_convert(); $is_photo = 0; - $x = @getimagesize($f); - logger('getimagesize: ' . print_r($x,true), LOGGER_DATA); - if (($x) && ($x[2] === IMAGETYPE_GIF || $x[2] === IMAGETYPE_JPEG || $x[2] === IMAGETYPE_PNG)) { + $gis = @getimagesize($f); + logger('getimagesize: ' . print_r($gis,true), LOGGER_DATA); + if (($gis) && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) { $is_photo = 1; } // updates entry with filesize and timestamp - $d = q("UPDATE attach SET filesize = '%s', is_photo = %d, edited = '%s' WHERE hash = '%s' AND uid = %d", + $d = q("UPDATE attach SET filesize = '%s', os_path = '%s', display_path = '%s', is_photo = %d, edited = '%s' WHERE hash = '%s' AND uid = %d", dbesc($size), + dbesc($xpath['os_path']), + dbesc($xpath['display_path']), intval($is_photo), dbesc($edited), dbesc($hash), @@ -312,29 +326,29 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { // check against service class quota $limit = engr_units_to_bytes(service_class_fetch($c[0]['channel_id'], 'attach_upload_limit')); if ($limit !== false) { - $x = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d ", + $z = q("SELECT SUM(filesize) AS total FROM attach WHERE aid = %d ", intval($c[0]['channel_account_id']) ); - if (($x) && ($x[0]['total'] + $size > $limit)) { - logger('service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $x[0]['total'] . ' limit is ' . userReadableSize($limit)); + if (($z) && ($z[0]['total'] + $size > $limit)) { + logger('service class limit exceeded for ' . $c[0]['channel_name'] . ' total usage is ' . $z[0]['total'] . ' limit is ' . userReadableSize($limit)); attach_delete($c[0]['channel_id'], $hash); return; } } - if ($is_photo) { + if($is_photo) { $album = ''; if ($this->folder_hash) { - $f1 = q("select filename from attach WHERE hash = '%s' AND uid = %d", + $f1 = q("select filename, display_path from attach WHERE hash = '%s' AND uid = %d", dbesc($this->folder_hash), intval($c[0]['channel_id']) ); if ($f1) - $album = $f1[0]['filename']; + $album = (($f1[0]['display_path']) ? $f1[0]['display_path'] : $f1[0]['filename']); } require_once('include/photos.php'); - $args = array( 'resource_id' => $hash, 'album' => $album, 'os_path' => $f, 'filename' => $name, 'getimagesize' => $x, 'directory' => $direct); + $args = array( 'resource_id' => $hash, 'album' => $album, 'os_syspath' => $f, 'os_path' => $xpath['os_path'], 'display_path' => $xpath['path'], 'filename' => $name, 'getimagesize' => $gis, 'directory' => $direct); $p = photo_upload($c[0], \App::get_observer(), $args); } @@ -646,20 +660,24 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { logger("Path mismatch: $path !== /$file"); return NULL; } - if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { - $prefix = 'DISTINCT ON (filename)'; - $suffix = 'ORDER BY filename'; - } - else { - $prefix = ''; - $suffix = 'GROUP BY filename'; - } + + $prefix = ''; + $suffix = ''; + $r = q("select $prefix id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, created, edited from attach where folder = '%s' and uid = %d $perms $suffix", dbesc($folder), intval($channel_id) ); foreach ($r as $rr) { + + // @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 + // name may or may not be accessible + + if($rr['revision']) + $rr['filename'] .= '-' . $rr['revision']; + //logger('filename: ' . $rr['filename'], LOGGER_DEBUG); if (intval($rr['is_dir'])) { $ret[] = new Directory($path . '/' . $rr['filename'], $auth); @@ -687,7 +705,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { $ret = array(); $r = q("SELECT channel_id, channel_address FROM channel WHERE channel_removed = 0 - AND channel_system = 0 AND NOT (channel_pageflags & %d)>0", + AND channel_system = 0 AND (channel_pageflags & %d) = 0", intval(PAGE_HIDDEN) ); diff --git a/Zotlabs/Storage/File.php b/Zotlabs/Storage/File.php index d2bca3964..1475241ab 100644 --- a/Zotlabs/Storage/File.php +++ b/Zotlabs/Storage/File.php @@ -85,13 +85,23 @@ class File extends DAV\Node implements DAV\IFile { intval($this->data['id']) ); + $x = attach_syspaths($this->auth->owner_id,$this->data['hash']); + + $y = q("update attach set display_path = '%s where hash = '%s' and uid = %d", + dbesc($x['path']), + dbesc($this->data['hash']), + intval($this->auth->owner_id) + ); + if($this->data->is_photo) { - $r = q("update photo set filename = '%s' where resource_id = '%s' and uid = %d", + $r = q("update photo set filename = '%s', display_path = '%s' where resource_id = '%s' and uid = %d", dbesc($newName), + dbesc($x['path']), dbesc($this->data['hash']), intval($this->auth->owner_id) ); } + $ch = channelx_by_n($this->auth->owner_id); if($ch) { $sync = attach_export_data($ch,$this->data['hash']); diff --git a/Zotlabs/Web/Router.php b/Zotlabs/Web/Router.php index ba2e78b25..3190369c8 100644 --- a/Zotlabs/Web/Router.php +++ b/Zotlabs/Web/Router.php @@ -62,12 +62,6 @@ class Router { } } - if((strpos($module,'admin') === 0) && (! is_site_admin())) { - \App::$module_loaded = false; - notice( t('Permission denied.') . EOL); - goaway(z_root()); - } - /* * If the site has a custom module to over-ride the standard module, use it. * Otherwise, look for the standard program module @@ -208,7 +202,7 @@ class Router { * The member may have also created a customised PDL that's stored in the config */ - load_pdl($a); + load_pdl(); /* * load current theme info diff --git a/Zotlabs/Web/WebServer.php b/Zotlabs/Web/WebServer.php index 5bb0e08e8..4e8dc6786 100644 --- a/Zotlabs/Web/WebServer.php +++ b/Zotlabs/Web/WebServer.php @@ -79,11 +79,6 @@ class WebServer { if(! x($_SESSION, 'sysmsg_info')) $_SESSION['sysmsg_info'] = array(); - /* - * check_config() is responsible for running update scripts. These automatically - * update the DB schema whenever we push a new one out. It also checks to see if - * any plugins have been added or removed and reacts accordingly. - */ if(\App::$install) { @@ -91,8 +86,16 @@ class WebServer { if(\App::$module != 'view') \App::$module = 'setup'; } - else - check_config($a); + else { + + /* + * check_config() is responsible for running update scripts. These automatically + * update the DB schema whenever we push a new one out. It also checks to see if + * any plugins have been added or removed and reacts accordingly. + */ + + check_config(); + } nav_set_selected('nothing'); @@ -130,7 +133,7 @@ class WebServer { call_hooks('page_end', \App::$page['content']); - construct_page($a); + construct_page(); killme(); } diff --git a/Zotlabs/Widget/Activity.php b/Zotlabs/Widget/Activity.php new file mode 100644 index 000000000..7264a3360 --- /dev/null +++ b/Zotlabs/Widget/Activity.php @@ -0,0 +1,61 @@ +<?php + +namespace Zotlabs\Widget; + +class Activity { + + function widget($arr) { + + if(! local_channel()) + return ''; + + $o = ''; + + if(is_array($arr) && array_key_exists('limit',$arr)) + $limit = " limit " . intval($limit) . " "; + else + $limit = ''; + + $perms_sql = item_permissions_sql(local_channel()) . item_normal(); + + $r = q("select author_xchan from item where item_unseen = 1 and uid = %d $perms_sql", + intval(local_channel()) + ); + + $contributors = []; + $arr = []; + + if($r) { + foreach($r as $rv) { + if(array_key_exists($rv['author_xchan'],$contributors)) { + $contributors[$rv['author_xchan']] ++; + } + else { + $contributors[$rv['author_xchan']] = 1; + } + } + foreach($contributors as $k => $v) { + $arr[] = [ 'author_xchan' => $k, 'total' => $v ]; + } + usort($arr,'total_sort'); + xchan_query($arr); + } + + $x = [ 'entries' => $arr ]; + call_hooks('activity_widget',$x); + $arr = $x['entries']; + + if($arr) { + $o .= '<div class="widget">'; + $o .= '<h3>' . t('Activity','widget') . '</h3><ul class="nav nav-pills flex-column">'; + + foreach($arr as $rv) { + $o .= '<li class="nav-item"><a class="nav-link" href="network?f=&xchan=' . urlencode($rv['author_xchan']) . '" ><span class="badge badge-default float-right">' . ((intval($rv['total'])) ? intval($rv['total']) : '') . '</span><img src="' . $rv['author']['xchan_photo_s'] . '" class="menu-img-1" /> ' . $rv['author']['xchan_name'] . '</a></li>'; + } + $o .= '</ul></div>'; + } + return $o; + } + +} + diff --git a/Zotlabs/Widget/Admin.php b/Zotlabs/Widget/Admin.php new file mode 100644 index 000000000..a761eebe3 --- /dev/null +++ b/Zotlabs/Widget/Admin.php @@ -0,0 +1,68 @@ +<?php + +namespace Zotlabs\Widget; + +class Admin { + + function widget($arr) { + + /* + * Side bar links + */ + + if(! is_site_admin()) { + return ''; + } + + $o = ''; + + // array( url, name, extra css classes ) + + $aside = [ + 'site' => array(z_root() . '/admin/site/', t('Site'), 'site'), + 'accounts' => array(z_root() . '/admin/accounts/', t('Accounts'), 'accounts', 'pending-update', t('Member registrations waiting for confirmation')), + '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'), + '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'), + 'dbsync' => array(z_root() . '/admin/dbsync/', t('DB updates'), 'dbsync') + ]; + + /* get plugins admin page */ + + $r = q("SELECT * FROM addon WHERE plugin_admin = 1"); + + $plugins = array(); + if($r) { + foreach ($r as $h){ + $plugin = $h['aname']; + $plugins[] = array(z_root() . '/admin/plugins/' . $plugin, $plugin, 'plugin'); + // temp plugins with admin + \App::$plugins_admin[] = $plugin; + } + } + + $logs = array(z_root() . '/admin/logs/', t('Logs'), 'logs'); + + $arr = array('links' => $aside,'plugins' => $plugins,'logs' => $logs); + call_hooks('admin_aside',$arr); + + $o .= replace_macros(get_markup_template('admin_aside.tpl'), array( + '$admin' => $aside, + '$admtxt' => t('Admin'), + '$plugadmtxt' => t('Plugin Features'), + '$plugins' => $plugins, + '$logtxt' => t('Logs'), + '$logs' => $logs, + '$h_pending' => t('Member registrations waiting for confirmation'), + '$admurl'=> z_root() . '/admin/' + )); + + return $o; + + } +} + diff --git a/Zotlabs/Widget/Affinity.php b/Zotlabs/Widget/Affinity.php new file mode 100644 index 000000000..439ba1f33 --- /dev/null +++ b/Zotlabs/Widget/Affinity.php @@ -0,0 +1,60 @@ +<?php + +namespace Zotlabs\Widget; + +class Affinity { + + function widget($arr) { + + if(! local_channel()) + return ''; + + // Get default cmin value from pconfig, but allow GET parameter to override + $cmin = intval(get_pconfig(local_channel(),'affinity','cmin')); + $cmin = (($cmin) ? $cmin : 0); + $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $cmin); + + // Get default cmax value from pconfig, but allow GET parameter to override + $cmax = intval(get_pconfig(local_channel(),'affinity','cmax')); + $cmax = (($cmax) ? $cmax : 99); + $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $cmax); + + + if(feature_enabled(local_channel(),'affinity')) { + + $labels = array( + t('Me'), + t('Family'), + t('Friends'), + t('Acquaintances'), + t('All') + ); + call_hooks('affinity_labels',$labels); + $label_str = ''; + + if($labels) { + foreach($labels as $l) { + if($label_str) { + $label_str .= ", '|'"; + $label_str .= ", '" . $l . "'"; + } + else + $label_str .= "'" . $l . "'"; + } + } + + $tpl = get_markup_template('main_slider.tpl'); + $x = replace_macros($tpl,array( + '$val' => $cmin . ',' . $cmax, + '$refresh' => t('Refresh'), + '$labels' => $label_str, + )); + + $arr = array('html' => $x); + call_hooks('main_slider',$arr); + return $arr['html']; + } + return ''; + } +} +
\ No newline at end of file diff --git a/Zotlabs/Widget/Album.php b/Zotlabs/Widget/Album.php new file mode 100644 index 000000000..f359e6d0f --- /dev/null +++ b/Zotlabs/Widget/Album.php @@ -0,0 +1,106 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/attach.php'); + +class Album { + + function widget($args) { + + + $owner_uid = \App::$profile_uid; + $sql_extra = permissions_sql($owner_uid); + + + if(! perm_is_allowed($owner_uid,get_observer_hash(),'view_storage')) + return ''; + + if($args['album']) + $album = $args['album']; + if($args['title']) + $title = $args['title']; + + /** + * This may return incorrect permissions if you have multiple directories of the same name. + * It is a limitation of the photo table using a name for a photo album instead of a folder hash + */ + + if($album) { + $x = q("select hash from attach where filename = '%s' and uid = %d limit 1", + dbesc($album), + intval($owner_uid) + ); + if($x) { + $y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']); + if(! $y) + return ''; + } + } + + $order = 'DESC'; + + $r = q("SELECT p.resource_id, p.id, p.filename, p.mimetype, p.imgscale, p.description, p.created FROM photo p INNER JOIN + (SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph + ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale) + ORDER BY created $order ", + intval($owner_uid), + dbesc($album), + intval(PHOTO_NORMAL), + intval(PHOTO_PROFILE) + ); + + //edit album name + $album_edit = null; + + $photos = array(); + if($r) { + $twist = 'rotright'; + foreach($r as $rr) { + + if($twist == 'rotright') + $twist = 'rotleft'; + else + $twist = 'rotright'; + + $ext = $phototypes[$rr['mimetype']]; + + $imgalt_e = $rr['filename']; + $desc_e = $rr['description']; + + $imagelink = (z_root() . '/photos/' . \App::$profile['channel_address'] . '/image/' . $rr['resource_id']); + + + $photos[] = array( + 'id' => $rr['id'], + 'twist' => ' ' . $twist . rand(2,4), + 'link' => $imagelink, + 'title' => t('View Photo'), + 'src' => z_root() . '/photo/' . $rr['resource_id'] . '-' . $rr['imgscale'] . '.' .$ext, + 'alt' => $imgalt_e, + 'desc'=> $desc_e, + 'ext' => $ext, + 'hash'=> $rr['resource_id'], + 'unknown' => t('Unknown') + ); + } + } + + + $tpl = get_markup_template('photo_album.tpl'); + $o .= replace_macros($tpl, array( + '$photos' => $photos, + '$album' => (($title) ? $title : $album), + '$album_id' => rand(), + '$album_edit' => array(t('Edit Album'), $album_edit), + '$can_post' => false, + '$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)), + '$order' => false, + '$upload_form' => $upload_form, + '$usage' => $usage_message + )); + + return $o; + } +} + diff --git a/Zotlabs/Widget/Appcategories.php b/Zotlabs/Widget/Appcategories.php new file mode 100644 index 000000000..490ec1abc --- /dev/null +++ b/Zotlabs/Widget/Appcategories.php @@ -0,0 +1,49 @@ +<?php + +namespace Zotlabs\Widget; + +class Appcategories { + + function widget($arr) { + + if(! local_channel()) + return ''; + + $selected = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : ''); + + // @FIXME ??? $srchurl undefined here - commented out until is reviewed + //$srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&'); + //$srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); + + // Leaving this line which negates the effect of the two invalid lines prior + $srchurl = z_root() . '/apps'; + + $terms = array(); + + $r = q("select distinct(term.term) + from term join app on term.oid = app.id + where app_channel = %d + and term.uid = app_channel + and term.otype = %d + and term.term != 'nav_featured_app' + order by term.term asc", + intval(local_channel()), + intval(TERM_OBJ_APP) + ); + + if($r) { + foreach($r as $rr) + $terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : '')); + + return replace_macros(get_markup_template('categories_widget.tpl'),array( + '$title' => t('Categories'), + '$desc' => '', + '$sel_all' => (($selected == '') ? 'selected' : ''), + '$all' => t('Everything'), + '$terms' => $terms, + '$base' => $srchurl, + + )); + } + } +} diff --git a/Zotlabs/Widget/Appcloud.php b/Zotlabs/Widget/Appcloud.php new file mode 100644 index 000000000..2a4671eee --- /dev/null +++ b/Zotlabs/Widget/Appcloud.php @@ -0,0 +1,13 @@ +<?php + +namespace Zotlabs\Widget; + +class Appcloud { + + function widget($arr) { + if(! local_channel()) + return ''; + return app_tagblock(z_root() . '/apps'); + } +} + diff --git a/Zotlabs/Widget/Archive.php b/Zotlabs/Widget/Archive.php new file mode 100644 index 000000000..c151ca563 --- /dev/null +++ b/Zotlabs/Widget/Archive.php @@ -0,0 +1,55 @@ +<?php + +namespace Zotlabs\Widget; + + +class Archive { + + function widget($arr) { + + $o = ''; + + if(! \App::$profile_uid) { + return ''; + } + + $uid = \App::$profile_uid; + + if(! feature_enabled($uid,'archives')) + return ''; + + if(! perm_is_allowed($uid,get_observer_hash(),'view_stream')) + return ''; + + $wall = ((array_key_exists('wall', $arr)) ? intval($arr['wall']) : 0); + $style = ((array_key_exists('style', $arr)) ? $arr['style'] : 'select'); + $showend = ((get_pconfig($uid,'system','archive_show_end_date')) ? true : false); + $mindate = get_pconfig($uid,'system','archive_mindate'); + $visible_years = get_pconfig($uid,'system','archive_visible_years'); + if(! $visible_years) + $visible_years = 5; + + $url = z_root() . '/' . \App::$cmd; + + $ret = list_post_dates($uid,$wall,$mindate); + + if(! count($ret)) + return ''; + + $cutoff_year = intval(datetime_convert('',date_default_timezone_get(),'now','Y')) - $visible_years; + $cutoff = ((array_key_exists($cutoff_year,$ret))? true : false); + + $o = replace_macros(get_markup_template('posted_date_widget.tpl'),array( + '$title' => t('Archives'), + '$size' => $visible_years, + '$cutoff_year' => $cutoff_year, + '$cutoff' => $cutoff, + '$url' => $url, + '$style' => $style, + '$showend' => $showend, + '$dates' => $ret + )); + return $o; + } +} + diff --git a/Zotlabs/Widget/Bookmarkedchats.php b/Zotlabs/Widget/Bookmarkedchats.php new file mode 100644 index 000000000..d64bbdb4b --- /dev/null +++ b/Zotlabs/Widget/Bookmarkedchats.php @@ -0,0 +1,28 @@ +<?php + +namespace Zotlabs\Widget; + +class Bookmarkedchats { + + function widget($arr) { + + if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) + return ''; + + $h = get_observer_hash(); + if(! $h) + return; + $r = q("select xchat_url, xchat_desc from xchat where xchat_xchan = '%s' order by xchat_desc", + dbesc($h) + ); + if($r) { + for($x = 0; $x < count($r); $x ++) { + $r[$x]['xchat_url'] = zid($r[$x]['xchat_url']); + } + } + return replace_macros(get_markup_template('bookmarkedchats.tpl'),array( + '$header' => t('Bookmarked Chatrooms'), + '$rooms' => $r + )); + } +} diff --git a/Zotlabs/Widget/Catcloud_wall.php b/Zotlabs/Widget/Catcloud_wall.php new file mode 100644 index 000000000..3795987cc --- /dev/null +++ b/Zotlabs/Widget/Catcloud_wall.php @@ -0,0 +1,19 @@ +<?php + +namespace Zotlabs\Widget; + +class Catcloud_wall { + + function widget($arr) { + + if((! \App::$profile['profile_uid']) || (! \App::$profile['channel_hash'])) + return ''; + if(! perm_is_allowed(\App::$profile['profile_uid'], get_observer_hash(), 'view_stream')) + return ''; + + $limit = ((array_key_exists('limit',$arr)) ? intval($arr['limit']) : 50); + + return catblock(\App::$profile['profile_uid'], $limit, '', \App::$profile['channel_hash'], 'wall'); + } + +} diff --git a/Zotlabs/Widget/Categories.php b/Zotlabs/Widget/Categories.php new file mode 100644 index 000000000..d1dcfda93 --- /dev/null +++ b/Zotlabs/Widget/Categories.php @@ -0,0 +1,23 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/contact_widgets.php'); + +class Categories { + + function widget($arr) { + + if((! \App::$profile['profile_uid']) + || (! perm_is_allowed(\App::$profile['profile_uid'],get_observer_hash(),'view_stream'))) { + return ''; + } + + $cat = ((x($_REQUEST,'cat')) ? htmlspecialchars($_REQUEST['cat'],ENT_COMPAT,'UTF-8') : ''); + $srchurl = \App::$query_string; + $srchurl = rtrim(preg_replace('/cat\=[^\&].*?(\&|$)/is','',$srchurl),'&'); + $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); + + return categories_widget($srchurl, $cat); + } +} diff --git a/Zotlabs/Widget/Chatroom_list.php b/Zotlabs/Widget/Chatroom_list.php new file mode 100644 index 000000000..e2aad0e05 --- /dev/null +++ b/Zotlabs/Widget/Chatroom_list.php @@ -0,0 +1,24 @@ +<?php + +namespace Zotlabs\Widget; + +class Chatroom_list { + + function widget($arr) { + + if(! \App::$profile) + return ''; + + $r = \Zotlabs\Lib\Chatroom::roomlist(\App::$profile['profile_uid']); + + if($r) { + return replace_macros(get_markup_template('chatroomlist.tpl'), array( + '$header' => t('Chatrooms'), + '$baseurl' => z_root(), + '$nickname' => \App::$profile['channel_address'], + '$items' => $r, + '$overview' => t('Overview') + )); + } + } +} diff --git a/Zotlabs/Widget/Chatroom_members.php b/Zotlabs/Widget/Chatroom_members.php new file mode 100644 index 000000000..8ed77fb3c --- /dev/null +++ b/Zotlabs/Widget/Chatroom_members.php @@ -0,0 +1,15 @@ +<?php + +namespace Zotlabs\Widget; + +class Chatroom_members { + + // The actual contents are filled in via AJAX + + function widget() { + return replace_macros(get_markup_template('chatroom_members.tpl'), array( + '$header' => t('Chat Members') + )); + } + +} diff --git a/Zotlabs/Widget/Clock.php b/Zotlabs/Widget/Clock.php new file mode 100644 index 000000000..b63b5f748 --- /dev/null +++ b/Zotlabs/Widget/Clock.php @@ -0,0 +1,63 @@ +<?php + +namespace Zotlabs\Widget; + +class Clock { + + function widget($arr) { + + $miltime = 0; + if(isset($arr['military']) && $arr['military']) + $miltime = 1; + + $o = <<< EOT +<div class="widget"> +<h3 class="clockface"></h3> +<script> + +var timerID = null +var timerRunning = false + +function stopclock(){ + if(timerRunning) + clearTimeout(timerID) + timerRunning = false +} + +function startclock(){ + stopclock() + showtime() +} + +function showtime(){ + var now = new Date() + var hours = now.getHours() + var minutes = now.getMinutes() + var seconds = now.getSeconds() + var military = $miltime + var timeValue = "" + if(military) + timeValue = hours + else + timeValue = ((hours > 12) ? hours - 12 : hours) + timeValue += ((minutes < 10) ? ":0" : ":") + minutes +// timeValue += ((seconds < 10) ? ":0" : ":") + seconds + if(! military) + timeValue += (hours >= 12) ? " P.M." : " A.M." + $('.clockface').html(timeValue) + timerID = setTimeout("showtime()",1000) + timerRunning = true +} + +$(document).ready(function() { + startclock(); +}); + +</script> +</div> +EOT; + + return $o; + } +} + diff --git a/Zotlabs/Widget/Collections.php b/Zotlabs/Widget/Collections.php new file mode 100644 index 000000000..d2b29679a --- /dev/null +++ b/Zotlabs/Widget/Collections.php @@ -0,0 +1,51 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/group.php'); + +class Collections { + + function widget($args) { + + $mode = ((array_key_exists('mode',$args)) ? $args['mode'] : 'conversation'); + switch($mode) { + case 'conversation': + $every = argv(0); + $each = argv(0); + $edit = true; + $current = $_REQUEST['gid']; + $abook_id = 0; + $wmode = 0; + break; + case 'connections': + $every = 'connections'; + $each = 'group'; + $edit = true; + $current = $_REQUEST['gid']; + $abook_id = 0; + $wmode = 0; + case 'groups': + $every = 'connections'; + $each = argv(0); + $edit = false; + $current = intval(argv(1)); + $abook_id = 0; + $wmode = 1; + break; + case 'abook': + $every = 'connections'; + $each = 'group'; + $edit = false; + $current = 0; + $abook_id = \App::$poi['abook_xchan']; + $wmode = 1; + break; + default: + return ''; + break; + } + + return group_side($every, $each, $edit, $current, $abook_id, $wmode); + } +} diff --git a/Zotlabs/Widget/Conversations.php b/Zotlabs/Widget/Conversations.php new file mode 100644 index 000000000..27e517c02 --- /dev/null +++ b/Zotlabs/Widget/Conversations.php @@ -0,0 +1,74 @@ +<?php + +namespace Zotlabs\Widget; + +class Conversations { + + function widget($arr) { + + if (! local_channel()) + return; + + if(argc() > 1) { + + switch(argv(1)) { + case 'combined': + $mailbox = 'combined'; + $header = t('Conversations'); + break; + case 'inbox': + $mailbox = 'inbox'; + $header = t('Received Messages'); + break; + case 'outbox': + $mailbox = 'outbox'; + $header = t('Sent Messages'); + break; + default: + $mailbox = 'combined'; + $header = t('Conversations'); + break; + } + + require_once('include/message.php'); + + // private_messages_list() can do other more complicated stuff, for now keep it simple + $r = private_messages_list(local_channel(), $mailbox, \App::$pager['start'], \App::$pager['itemspage']); + + if(! $r) { + info( t('No messages.') . EOL); + return $o; + } + + $messages = array(); + + foreach($r as $rr) { + + $messages[] = array( + 'mailbox' => $mailbox, + 'id' => $rr['id'], + 'from_name' => $rr['from']['xchan_name'], + 'from_url' => chanlink_hash($rr['from_xchan']), + 'from_photo' => $rr['from']['xchan_photo_s'], + 'to_name' => $rr['to']['xchan_name'], + 'to_url' => chanlink_hash($rr['to_xchan']), + 'to_photo' => $rr['to']['xchan_photo_s'], + 'subject' => (($rr['seen']) ? $rr['title'] : '<strong>' . $rr['title'] . '</strong>'), + 'delete' => t('Delete conversation'), + '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'])) + ); + } + + $tpl = get_markup_template('mail_head.tpl'); + $o .= replace_macros($tpl, array( + '$header' => $header, + '$messages' => $messages + )); + + } + return $o; + } +} diff --git a/Zotlabs/Widget/Cover_photo.php b/Zotlabs/Widget/Cover_photo.php new file mode 100644 index 000000000..d2eb1be92 --- /dev/null +++ b/Zotlabs/Widget/Cover_photo.php @@ -0,0 +1,59 @@ +<?php + +namespace Zotlabs\Widget; + +class Cover_photo { + + function widget($arr) { + + require_once('include/channel.php'); + $o = ''; + + if(\App::$module == 'channel' && $_REQUEST['mid']) + return ''; + + $channel_id = 0; + if(array_key_exists('channel_id', $arr) && intval($arr['channel_id'])) + $channel_id = intval($arr['channel_id']); + if(! $channel_id) + $channel_id = \App::$profile_uid; + if(! $channel_id) + return ''; + + $channel = channelx_by_n($channel_id); + + if(array_key_exists('style', $arr) && isset($arr['style'])) + $style = $arr['style']; + else + $style = 'width:100%; height: auto;'; + + // ensure they can't sneak in an eval(js) function + + if(strpbrk($style,'(\'"<>') !== false) + $style = ''; + + if(array_key_exists('title', $arr) && isset($arr['title'])) + $title = $arr['title']; + else + $title = $channel['channel_name']; + + if(array_key_exists('subtitle', $arr) && isset($arr['subtitle'])) + $subtitle = $arr['subtitle']; + else + $subtitle = str_replace('@','@',$channel['xchan_addr']); + + $c = get_cover_photo($channel_id,'html'); + + if($c) { + $photo_html = (($style) ? str_replace('alt=',' style="' . $style . '" alt=',$c) : $c); + + $o = replace_macros(get_markup_template('cover_photo_widget.tpl'),array( + '$photo_html' => $photo_html, + '$title' => $title, + '$subtitle' => $subtitle, + '$hovertitle' => t('Click to show more'), + )); + } + return $o; + } +} diff --git a/Zotlabs/Widget/Design_tools.php b/Zotlabs/Widget/Design_tools.php new file mode 100644 index 000000000..8ab6a235d --- /dev/null +++ b/Zotlabs/Widget/Design_tools.php @@ -0,0 +1,21 @@ +<?php + +namespace Zotlabs\Widget; + +class Design_tools { + + function widget($arr) { + + // mod menu doesn't load a profile. For any modules which load a profile, check it. + // otherwise local_channel() is sufficient for permissions. + + if(\App::$profile['profile_uid']) + if((\App::$profile['profile_uid'] != local_channel()) && (! \App::$is_sys)) + return ''; + + if(! local_channel()) + return ''; + + return design_tools(); + } +}
\ No newline at end of file diff --git a/Zotlabs/Widget/Dirsort.php b/Zotlabs/Widget/Dirsort.php new file mode 100644 index 000000000..e75a00e50 --- /dev/null +++ b/Zotlabs/Widget/Dirsort.php @@ -0,0 +1,11 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/dir_fns.php'); + +class Dirsort { + function widget($arr) { + return dir_sort_links(); + } +} diff --git a/Zotlabs/Widget/Dirtags.php b/Zotlabs/Widget/Dirtags.php new file mode 100644 index 000000000..f211d5942 --- /dev/null +++ b/Zotlabs/Widget/Dirtags.php @@ -0,0 +1,13 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/dir_fns.php'); + +class Dirtags { + + function widget($arr) { + return dir_tagblock(z_root() . '/directory', null); + } + +} diff --git a/Zotlabs/Widget/Eventstools.php b/Zotlabs/Widget/Eventstools.php new file mode 100644 index 000000000..7efd3f72e --- /dev/null +++ b/Zotlabs/Widget/Eventstools.php @@ -0,0 +1,19 @@ +<?php + +namespace Zotlabs\Widget; + +class Eventstools { + + function widget($arr) { + + if(! local_channel()) + return; + + return replace_macros(get_markup_template('events_tools_side.tpl'), array( + '$title' => t('Events Tools'), + '$export' => t('Export Calendar'), + '$import' => t('Import Calendar'), + '$submit' => t('Submit') + )); + } +} diff --git a/Zotlabs/Widget/Filer.php b/Zotlabs/Widget/Filer.php new file mode 100644 index 000000000..5d6f96a87 --- /dev/null +++ b/Zotlabs/Widget/Filer.php @@ -0,0 +1,36 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/contact_widgets.php'); + +class Filer { + + function widget($arr) { + if(! local_channel()) + return ''; + + + $selected = ((x($_REQUEST,'file')) ? $_REQUEST['file'] : ''); + + $terms = array(); + $r = q("select distinct term from term where uid = %d and ttype = %d order by term asc", + intval(local_channel()), + intval(TERM_FILE) + ); + if(! $r) + return; + + foreach($r as $rr) + $terms[] = array('name' => $rr['term'], 'selected' => (($selected == $rr['term']) ? 'selected' : '')); + + return replace_macros(get_markup_template('fileas_widget.tpl'),array( + '$title' => t('Saved Folders'), + '$desc' => '', + '$sel_all' => (($selected == '') ? 'selected' : ''), + '$all' => t('Everything'), + '$terms' => $terms, + '$base' => z_root() . '/' . \App::$cmd + )); + } +} diff --git a/Zotlabs/Widget/Findpeople.php b/Zotlabs/Widget/Findpeople.php new file mode 100644 index 000000000..f450b96ae --- /dev/null +++ b/Zotlabs/Widget/Findpeople.php @@ -0,0 +1,12 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/contact_widgets.php'); + +class Findpeople { + function widget($arr) { + return findpeople_widget(); + } +} + diff --git a/Zotlabs/Widget/Follow.php b/Zotlabs/Widget/Follow.php new file mode 100644 index 000000000..c4aecc8e1 --- /dev/null +++ b/Zotlabs/Widget/Follow.php @@ -0,0 +1,37 @@ +<?php + +namespace Zotlabs\Widget; + + +class Follow { + + function widget($args) { + if(! local_channel()) + return ''; + + $uid = \App::$channel['channel_id']; + $r = q("select count(*) as total from abook where abook_channel = %d and abook_self = 0 ", + intval($uid) + ); + + if($r) + $total_channels = $r[0]['total']; + + $limit = service_class_fetch($uid,'total_channels'); + if($limit !== false) { + $abook_usage_message = sprintf( t("You have %1$.0f of %2$.0f allowed connections."), $total_channels, $limit); + } + else { + $abook_usage_message = ''; + } + + return replace_macros(get_markup_template('follow.tpl'),array( + '$connect' => t('Add New Connection'), + '$desc' => t('Enter channel address'), + '$hint' => t('Examples: bob@example.com, https://example.com/barbara'), + '$follow' => t('Connect'), + '$abook_usage_message' => $abook_usage_message + )); + } +} + diff --git a/Zotlabs/Widget/Forums.php b/Zotlabs/Widget/Forums.php new file mode 100644 index 000000000..67e498b24 --- /dev/null +++ b/Zotlabs/Widget/Forums.php @@ -0,0 +1,97 @@ +<?php + +namespace Zotlabs\Widget; + +class Forums { + + function widget($arr) { + + if(! local_channel()) + return ''; + + $o = ''; + + if(is_array($arr) && array_key_exists('limit',$arr)) + $limit = " limit " . intval($limit) . " "; + else + $limit = ''; + + $unseen = 0; + if(is_array($arr) && array_key_exists('unseen',$arr) && intval($arr['unseen'])) + $unseen = 1; + + $perms_sql = item_permissions_sql(local_channel()) . item_normal(); + + $xf = false; + + $x1 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'send_stream' and v = '0'", + intval(local_channel()) + ); + if($x1) { + $xc = ids_to_querystr($x1,'xchan',true); + $x2 = q("select xchan from abconfig where chan = %d and cat = 'their_perms' and k = 'tag_deliver' and v = '1' and xchan in (" . $xc . ") ", + intval(local_channel()) + ); + if($x2) + $xf = ids_to_querystr($x2,'xchan',true); + } + + $sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 "); + + $r1 = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d $sql_extra order by xchan_name $limit ", + intval(local_channel()) + ); + if(! $r1) + return $o; + + $str = ''; + + // Trying to cram all this into a single query with joins and the proper group by's is tough. + // There also should be a way to update this via ajax. + + for($x = 0; $x < count($r1); $x ++) { + $r = q("select sum(item_unseen) as unseen from item where owner_xchan = '%s' and uid = %d and item_unseen = 1 $perms_sql ", + dbesc($r1[$x]['xchan_hash']), + intval(local_channel()) + ); + if($r) + $r1[$x]['unseen'] = $r[0]['unseen']; + + /** + * @FIXME + * This SQL makes the counts correct when you get forum posts arriving from different routes/sources + * (like personal channels). However the network query for these posts doesn't yet include this + * correction and it makes the SQL for that query pretty hairy so this is left as a future exercise. + * It may make more sense in that query to look for the mention in the body rather than another join, + * but that makes it very inefficient. + * + $r = q("select sum(item_unseen) as unseen from item left join term on oid = id where otype = %d and owner_xchan != '%s' and item.uid = %d and url = '%s' and ttype = %d $perms_sql ", + intval(TERM_OBJ_POST), + dbesc($r1[$x]['xchan_hash']), + intval(local_channel()), + dbesc($r1[$x]['xchan_url']), + intval(TERM_MENTION) + ); + if($r) + $r1[$x]['unseen'] = ((array_key_exists('unseen',$r1[$x])) ? $r1[$x]['unseen'] + $r[0]['unseen'] : $r[0]['unseen']); + * + * end @FIXME + */ + + } + + if($r1) { + $o .= '<div class="widget">'; + $o .= '<h3>' . t('Forums') . '</h3><ul class="nav nav-pills flex-column">'; + + foreach($r1 as $rr) { + if($unseen && (! intval($rr['unseen']))) + continue; + $o .= '<li class="nav-item"><a class="nav-link" href="network?f=&pf=1&cid=' . $rr['abook_id'] . '" ><span class="badge badge-default float-right">' . ((intval($rr['unseen'])) ? intval($rr['unseen']) : '') . '</span><img class ="menu-img-1" src="' . $rr['xchan_photo_s'] . '" /> ' . $rr['xchan_name'] . '</a></li>'; + } + $o .= '</ul></div>'; + } + return $o; + + } +} diff --git a/Zotlabs/Widget/Fullprofile.php b/Zotlabs/Widget/Fullprofile.php new file mode 100644 index 000000000..d7340ef40 --- /dev/null +++ b/Zotlabs/Widget/Fullprofile.php @@ -0,0 +1,16 @@ +<?php + +namespace Zotlabs\Widget; + +class Fullprofile { + + function widget($arr) { + + if(! \App::$profile['profile_uid']) + return; + + $block = observer_prohibited(); + + return profile_sidebar(\App::$profile, $block); + } +} diff --git a/Zotlabs/Widget/Helpindex.php b/Zotlabs/Widget/Helpindex.php new file mode 100644 index 000000000..f23e73e75 --- /dev/null +++ b/Zotlabs/Widget/Helpindex.php @@ -0,0 +1,45 @@ +<?php + +namespace Zotlabs\Widget; + +class Helpindex { + + function widget($arr) { + + $o .= '<div class="widget">'; + + $level_0 = get_help_content('sitetoc'); + if(! $level_0) + $level_0 = get_help_content('toc'); + + $level_0 = preg_replace('/\<ul(.*?)\>/','<ul class="nav nav-pills flex-column">',$level_0); + + $levels = array(); + + + if(argc() > 2) { + $path = ''; + for($x = 1; $x < argc(); $x ++) { + $path .= argv($x) . '/'; + $y = get_help_content($path . 'sitetoc'); + if(! $y) + $y = get_help_content($path . 'toc'); + if($y) + $levels[] = preg_replace('/\<ul(.*?)\>/','<ul class="nav nav-pills flex-column">',$y); + } + } + + if($level_0) + $o .= $level_0; + if($levels) { + foreach($levels as $l) { + $o .= '<br /><br />'; + $o .= $l; + } + } + + $o .= '</div>'; + + return $o; + } +} diff --git a/Zotlabs/Widget/Item.php b/Zotlabs/Widget/Item.php new file mode 100644 index 000000000..273d5649c --- /dev/null +++ b/Zotlabs/Widget/Item.php @@ -0,0 +1,54 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/security.php'); + +class Item { + + function widget($arr) { + + $channel_id = 0; + if(array_key_exists('channel_id',$arr) && intval($arr['channel_id'])) + $channel_id = intval($arr['channel_id']); + if(! $channel_id) + $channel_id = \App::$profile_uid; + if(! $channel_id) + return ''; + + + if((! $arr['mid']) && (! $arr['title'])) + return ''; + + if(! perm_is_allowed($channel_id, get_observer_hash(), 'view_pages')) + return ''; + + $sql_extra = item_permissions_sql($channel_id); + + if($arr['title']) { + $r = q("select item.* from item left join iconfig on item.id = iconfig.iid + where item.uid = %d and iconfig.cat = 'system' and iconfig.v = '%s' + and iconfig.k = 'WEBPAGE' and item_type = %d $sql_options $revision limit 1", + intval($channel_id), + dbesc($arr['title']), + intval(ITEM_TYPE_WEBPAGE) + ); + } + else { + $r = q("select * from item where mid = '%s' and uid = %d and item_type = " + . intval(ITEM_TYPE_WEBPAGE) . " $sql_extra limit 1", + dbesc($arr['mid']), + intval($channel_id) + ); + } + + if(! $r) + return ''; + + xchan_query($r); + $r = fetch_post_tags($r, true); + + $o = prepare_page($r[0]); + return $o; + } +} diff --git a/Zotlabs/Widget/Mailmenu.php b/Zotlabs/Widget/Mailmenu.php new file mode 100644 index 000000000..512f7d9c0 --- /dev/null +++ b/Zotlabs/Widget/Mailmenu.php @@ -0,0 +1,36 @@ +<?php + +namespace Zotlabs\Widget; + +class Mailmenu { + + function widget($arr) { + + if (! local_channel()) + return; + + return replace_macros(get_markup_template('message_side.tpl'), array( + '$title' => t('Private Mail Menu'), + '$combined' => array( + 'label' => t('Combined View'), + 'url' => z_root() . '/mail/combined', + 'sel' => (argv(1) == 'combined'), + ), + '$inbox' => array( + 'label' => t('Inbox'), + 'url' => z_root() . '/mail/inbox', + 'sel' => (argv(1) == 'inbox'), + ), + '$outbox' => array( + 'label' => t('Outbox'), + 'url' => z_root() . '/mail/outbox', + 'sel' => (argv(1) == 'outbox'), + ), + '$new' => array( + 'label' => t('New Message'), + 'url' => z_root() . '/mail/new', + 'sel'=> (argv(1) == 'new'), + ) + )); + } +} diff --git a/Zotlabs/Widget/Menu_preview.php b/Zotlabs/Widget/Menu_preview.php new file mode 100644 index 000000000..51218f6cf --- /dev/null +++ b/Zotlabs/Widget/Menu_preview.php @@ -0,0 +1,16 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/menu.php'); + +class Menu_preview { + + function widget($arr) { + if(! \App::$data['menu_item']) + return; + + return menu_render(\App::$data['menu_item']); + } + +} diff --git a/Zotlabs/Widget/Notes.php b/Zotlabs/Widget/Notes.php new file mode 100644 index 000000000..5c83a550f --- /dev/null +++ b/Zotlabs/Widget/Notes.php @@ -0,0 +1,23 @@ +<?php + +namespace Zotlabs\Widget; + +class Notes { + + function widget($arr) { + if(! local_channel()) + return ''; + if(! feature_enabled(local_channel(),'private_notes')) + return ''; + + $text = get_pconfig(local_channel(),'notes','text'); + + $o = replace_macros(get_markup_template('notes.tpl'), array( + '$banner' => t('Notes'), + '$text' => $text, + '$save' => t('Save'), + )); + + return $o; + } +} diff --git a/Zotlabs/Widget/Photo.php b/Zotlabs/Widget/Photo.php new file mode 100644 index 000000000..10031f028 --- /dev/null +++ b/Zotlabs/Widget/Photo.php @@ -0,0 +1,55 @@ +<?php + +namespace Zotlabs\Widget; + + +class Photo { + + + /** + * @brief Widget to display a single photo. + * + * @param array $arr associative array with + * * \e string \b src URL of photo; URL must be an http or https URL + * * \e boolean \b zrl use zid in URL + * * \e string \b style CSS string + * + * @return string with parsed HTML + */ + + function widget($arr) { + + $style = $zrl = false; + + if(array_key_exists('src', $arr) && isset($arr['src'])) + $url = $arr['src']; + + if(strpos($url, 'http') !== 0) + return ''; + + if(array_key_exists('style', $arr) && isset($arr['style'])) + $style = $arr['style']; + + // ensure they can't sneak in an eval(js) function + + if(strpbrk($style, '(\'"<>' ) !== false) + $style = ''; + + if(array_key_exists('zrl', $arr) && isset($arr['zrl'])) + $zrl = (($arr['zrl']) ? true : false); + + if($zrl) + $url = zid($url); + + $o = '<div class="widget">'; + + $o .= '<img ' . (($zrl) ? ' class="zrl" ' : '') + . (($style) ? ' style="' . $style . '"' : '') + . ' src="' . $url . '" alt="' . t('photo/image') . '">'; + + $o .= '</div>'; + + return $o; + } +} + diff --git a/Zotlabs/Widget/Photo_albums.php b/Zotlabs/Widget/Photo_albums.php new file mode 100644 index 000000000..6df8ddf3c --- /dev/null +++ b/Zotlabs/Widget/Photo_albums.php @@ -0,0 +1,25 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/photos.php'); + +class Photo_albums { + + function widget($arr) { + + if(! \App::$profile['profile_uid']) + return ''; + + $channelx = channelx_by_n(\App::$profile['profile_uid']); + + if((! $channelx) || (! perm_is_allowed(\App::$profile['profile_uid'], get_observer_hash(), 'view_storage'))) + return ''; + + $sortkey = ((array_key_exists('sortkey',$arr)) ? $arr['sortkey'] : 'display_path'); + $direction = ((array_key_exists('direction',$arr)) ? $arr['direction'] : 'asc'); + + return photos_album_widget($channelx, \App::get_observer(),$sortkey,$direction); + } +} + diff --git a/Zotlabs/Widget/Photo_rand.php b/Zotlabs/Widget/Photo_rand.php new file mode 100644 index 000000000..af80a3b9f --- /dev/null +++ b/Zotlabs/Widget/Photo_rand.php @@ -0,0 +1,66 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/photos.php'); + +class Photo_rand { + + function widget($arr) { + + $style = false; + + if(array_key_exists('album', $arr) && isset($arr['album'])) + $album = $arr['album']; + else + $album = ''; + + $channel_id = 0; + if(array_key_exists('channel_id', $arr) && intval($arr['channel_id'])) + $channel_id = intval($arr['channel_id']); + if(! $channel_id) + $channel_id = \App::$profile_uid; + if(! $channel_id) + return ''; + + $scale = ((array_key_exists('scale',$arr)) ? intval($arr['scale']) : 0); + + $ret = photos_list_photos(array('channel_id' => $channel_id),\App::get_observer(),$album); + + $filtered = array(); + if($ret['success'] && $ret['photos']) + foreach($ret['photos'] as $p) + if($p['imgscale'] == $scale) + $filtered[] = $p['src']; + + if($filtered) { + $e = mt_rand(0, count($filtered) - 1); + $url = $filtered[$e]; + } + + if(strpos($url, 'http') !== 0) + return ''; + + if(array_key_exists('style', $arr) && isset($arr['style'])) + $style = $arr['style']; + + // ensure they can't sneak in an eval(js) function + + if(strpos($style,'(') !== false) + return ''; + + $url = zid($url); + + $o = '<div class="widget">'; + + $o .= '<img class="zrl" ' + . (($style) ? ' style="' . $style . '"' : '') + . ' src="' . $url . '" alt="' . t('photo/image') . '">'; + + $o .= '</div>'; + + return $o; + } +} + + diff --git a/Zotlabs/Widget/Profile.php b/Zotlabs/Widget/Profile.php new file mode 100644 index 000000000..bffd910b6 --- /dev/null +++ b/Zotlabs/Widget/Profile.php @@ -0,0 +1,13 @@ +<?php + +namespace Zotlabs\Widget; + + +class Profile { + + function widget($args) { + $block = observer_prohibited(); + return profile_sidebar(\App::$profile, $block, true); + } + +}
\ No newline at end of file diff --git a/Zotlabs/Widget/Pubsites.php b/Zotlabs/Widget/Pubsites.php new file mode 100644 index 000000000..958ba68c2 --- /dev/null +++ b/Zotlabs/Widget/Pubsites.php @@ -0,0 +1,16 @@ +<?php + +namespace Zotlabs\Widget; + +class Pubsites { + + // used by site ratings pages to provide a return link + + function widget($arr) { + if(\App::$poi) + return; + return '<div class="widget"><ul class="nav nav-pills"><li><a href="pubsites">' . t('Public Hubs') . '</a></li></ul></div>'; + } +} + + diff --git a/Zotlabs/Widget/Random_block.php b/Zotlabs/Widget/Random_block.php new file mode 100644 index 000000000..465a51f97 --- /dev/null +++ b/Zotlabs/Widget/Random_block.php @@ -0,0 +1,46 @@ +<?php + +namespace Zotlabs\Widget; + +class Random_block { + + function widget($arr) { + + $channel_id = 0; + if(array_key_exists('channel_id',$arr) && intval($arr['channel_id'])) + $channel_id = intval($arr['channel_id']); + if(! $channel_id) + $channel_id = \App::$profile_uid; + if(! $channel_id) + return ''; + + if(array_key_exists('contains',$arr)) + $contains = $arr['contains']; + + $o = ''; + + require_once('include/security.php'); + $sql_options = item_permissions_sql($channel_id); + + $randfunc = db_getfunc('RAND'); + + $r = q("select item.* from item left join iconfig on item.id = iconfig.iid + where item.uid = %d and iconfig.cat = 'system' and iconfig.v like '%s' and iconfig.k = 'BUILDBLOCK' and + item_type = %d $sql_options order by $randfunc limit 1", + intval($channel_id), + dbesc('%' . $contains . '%'), + intval(ITEM_TYPE_BLOCK) + ); + + if($r) { + $o = '<div class="widget bblock">'; + if($r[0]['title']) + $o .= '<h3>' . $r[0]['title'] . '</h3>'; + + $o .= prepare_text($r[0]['body'],$r[0]['mimetype']); + $o .= '</div>'; + } + + return $o; + } +} diff --git a/Zotlabs/Widget/Rating.php b/Zotlabs/Widget/Rating.php new file mode 100644 index 000000000..5e09f457b --- /dev/null +++ b/Zotlabs/Widget/Rating.php @@ -0,0 +1,67 @@ +<?php + +namespace Zotlabs\Widget; + +class Rating { + + function widget($arr) { + + + $rating_enabled = get_config('system','rating_enabled'); + if(! $rating_enabled) { + return; + } + + if($arr['target']) + $hash = $arr['target']; + else + $hash = \App::$poi['xchan_hash']; + + if(! $hash) + return; + + $url = ''; + $remote = false; + + if(remote_channel() && ! local_channel()) { + $ob = \App::get_observer(); + if($ob && $ob['xchan_url']) { + $p = parse_url($ob['xchan_url']); + if($p) { + $url = $p['scheme'] . '://' . $p['host'] . (($p['port']) ? ':' . $p['port'] : ''); + $url .= '/rate?f=&target=' . urlencode($hash); + } + $remote = true; + } + } + + $self = false; + + if(local_channel()) { + $channel = \App::get_channel(); + + if($hash == $channel['channel_hash']) + $self = true; + + head_add_js('ratings.js'); + } + + + $o = '<div class="widget">'; + $o .= '<h3>' . t('Rating Tools') . '</h3>'; + + if((($remote) || (local_channel())) && (! $self)) { + if($remote) + $o .= '<a class="btn btn-block btn-primary btn-sm" href="' . $url . '"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</a>'; + else + $o .= '<div class="btn btn-block btn-primary btn-sm" onclick="doRatings(\'' . $hash . '\'); return false;"><i class="fa fa-pencil"></i> ' . t('Rate Me') . '</div>'; + } + + $o .= '<a class="btn btn-block btn-default btn-sm" href="ratings/' . $hash . '"><i class="fa fa-eye"></i> ' . t('View Ratings') . '</a>'; + $o .= '</div>'; + + return $o; + + } +} + diff --git a/Zotlabs/Widget/Savedsearch.php b/Zotlabs/Widget/Savedsearch.php new file mode 100644 index 000000000..378c27139 --- /dev/null +++ b/Zotlabs/Widget/Savedsearch.php @@ -0,0 +1,91 @@ +<?php + +namespace Zotlabs\Widget; + +class Savedsearch { + + function widget($arr) { + + if((! local_channel()) || (! feature_enabled(local_channel(),'savedsearch'))) + return ''; + + $search = ((x($_GET,'netsearch')) ? $_GET['netsearch'] : ''); + if(! $search) + $search = ((x($_GET,'search')) ? $_GET['search'] : ''); + + if(x($_GET,'searchsave') && $search) { + $r = q("select * from term where uid = %d and ttype = %d and term = '%s' limit 1", + intval(local_channel()), + intval(TERM_SAVEDSEARCH), + dbesc($search) + ); + if(! $r) { + q("insert into term ( uid,ttype,term ) values ( %d, %d, '%s') ", + intval(local_channel()), + intval(TERM_SAVEDSEARCH), + dbesc($search) + ); + } + } + + if(x($_GET,'searchremove') && $search) { + q("delete from term where uid = %d and ttype = %d and term = '%s'", + intval(local_channel()), + intval(TERM_SAVEDSEARCH), + dbesc($search) + ); + $search = ''; + } + + $srchurl = \App::$query_string; + + $srchurl = rtrim(preg_replace('/searchsave\=[^\&].*?(\&|$)/is','',$srchurl),'&'); + $hasq = ((strpos($srchurl,'?') !== false) ? true : false); + $srchurl = rtrim(preg_replace('/searchremove\=[^\&].*?(\&|$)/is','',$srchurl),'&'); + + $srchurl = rtrim(preg_replace('/search\=[^\&].*?(\&|$)/is','',$srchurl),'&'); + $srchurl = rtrim(preg_replace('/submit\=[^\&].*?(\&|$)/is','',$srchurl),'&'); + $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); + + + $hasq = ((strpos($srchurl,'?') !== false) ? true : false); + $hasamp = ((strpos($srchurl,'&') !== false) ? true : false); + + if(($hasamp) && (! $hasq)) + $srchurl = substr($srchurl,0,strpos($srchurl,'&')) . '?f=&' . substr($srchurl,strpos($srchurl,'&')+1); + + $o = ''; + + $r = q("select tid,term from term WHERE uid = %d and ttype = %d ", + intval(local_channel()), + intval(TERM_SAVEDSEARCH) + ); + + $saved = array(); + + if(count($r)) { + foreach($r as $rr) { + $saved[] = array( + 'id' => $rr['tid'], + 'term' => $rr['term'], + 'dellink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&searchremove=1&search=' . urlencode($rr['term']), + 'srchlink' => z_root() . '/' . $srchurl . (($hasq || $hasamp) ? '' : '?f=') . '&search=' . urlencode($rr['term']), + 'displayterm' => htmlspecialchars($rr['term'], ENT_COMPAT,'UTF-8'), + 'encodedterm' => urlencode($rr['term']), + 'delete' => t('Remove term'), + 'selected' => ($search==$rr['term']), + ); + } + } + + $tpl = get_markup_template("saved_searches.tpl"); + $o = replace_macros($tpl, array( + '$title' => t('Saved Searches'), + '$add' => t('add'), + '$searchbox' => searchbox($search, 'netsearch-box', $srchurl . (($hasq) ? '' : '?f='), true), + '$saved' => $saved, + )); + + return $o; + } +} diff --git a/Zotlabs/Widget/Settings_menu.php b/Zotlabs/Widget/Settings_menu.php new file mode 100644 index 000000000..753390c23 --- /dev/null +++ b/Zotlabs/Widget/Settings_menu.php @@ -0,0 +1,137 @@ +<?php + +namespace Zotlabs\Widget; + +class Settings_menu { + + function widget($arr) { + + if(! local_channel()) + return; + + + $channel = \App::get_channel(); + + $abook_self_id = 0; + + // Retrieve the 'self' address book entry for use in the auto-permissions link + + $role = get_pconfig(local_channel(),'system','permissions_role'); + + $abk = q("select abook_id from abook where abook_channel = %d and abook_self = 1 limit 1", + intval(local_channel()) + ); + if($abk) + $abook_self_id = $abk[0]['abook_id']; + + $x = q("select count(*) as total from hubloc where hubloc_hash = '%s' and hubloc_deleted = 0 ", + dbesc($channel['channel_hash']) + ); + + $hublocs = (($x && $x[0]['total'] > 1) ? true : false); + + $tabs = array( + array( + 'label' => t('Account settings'), + 'url' => z_root().'/settings/account', + 'selected' => ((argv(1) === 'account') ? 'active' : ''), + ), + + array( + 'label' => t('Channel settings'), + 'url' => z_root().'/settings/channel', + 'selected' => ((argv(1) === 'channel') ? 'active' : ''), + ), + + ); + + if(get_account_techlevel() > 0 && get_features()) { + $tabs[] = array( + 'label' => t('Additional features'), + 'url' => z_root().'/settings/features', + 'selected' => ((argv(1) === 'features') ? 'active' : ''), + ); + } + + $tabs[] = array( + 'label' => t('Feature/Addon settings'), + 'url' => z_root().'/settings/featured', + 'selected' => ((argv(1) === 'featured') ? 'active' : ''), + ); + + $tabs[] = array( + 'label' => t('Display settings'), + 'url' => z_root().'/settings/display', + 'selected' => ((argv(1) === 'display') ? 'active' : ''), + ); + + if($hublocs) { + $tabs[] = array( + 'label' => t('Manage locations'), + 'url' => z_root() . '/locs', + 'selected' => ((argv(1) === 'locs') ? 'active' : ''), + ); + } + + $tabs[] = array( + 'label' => t('Export channel'), + 'url' => z_root() . '/uexport', + 'selected' => '' + ); + + $tabs[] = array( + 'label' => t('Connected apps'), + 'url' => z_root() . '/settings/oauth', + 'selected' => ((argv(1) === 'oauth') ? 'active' : ''), + ); + + if(get_account_techlevel() > 2) { + $tabs[] = array( + 'label' => t('Guest Access Tokens'), + 'url' => z_root() . '/settings/tokens', + 'selected' => ((argv(1) === 'tokens') ? 'active' : ''), + ); + } + + if(feature_enabled(local_channel(),'permcats')) { + $tabs[] = array( + 'label' => t('Permission Groups'), + 'url' => z_root() . '/settings/permcats', + 'selected' => ((argv(1) === 'permcats') ? 'active' : ''), + ); + } + + + if($role === false || $role === 'custom') { + $tabs[] = array( + 'label' => t('Connection Default Permissions'), + 'url' => z_root() . '/connedit/' . $abook_self_id, + 'selected' => '' + ); + } + + if(feature_enabled(local_channel(),'premium_channel')) { + $tabs[] = array( + 'label' => t('Premium Channel Settings'), + 'url' => z_root() . '/connect/' . $channel['channel_address'], + 'selected' => '' + ); + } + + if(feature_enabled(local_channel(),'channel_sources')) { + $tabs[] = array( + 'label' => t('Channel Sources'), + 'url' => z_root() . '/sources', + 'selected' => '' + ); + } + + $tabtpl = get_markup_template("generic_links_widget.tpl"); + return replace_macros($tabtpl, array( + '$title' => t('Settings'), + '$class' => 'settings-widget', + '$items' => $tabs, + )); + } + +}
\ No newline at end of file diff --git a/Zotlabs/Widget/Shortprofile.php b/Zotlabs/Widget/Shortprofile.php new file mode 100644 index 000000000..9c2a46e75 --- /dev/null +++ b/Zotlabs/Widget/Shortprofile.php @@ -0,0 +1,18 @@ +<?php + +namespace Zotlabs\Widget; + +class Shortprofile { + + function widget($arr) { + + if(! \App::$profile['profile_uid']) + return; + + $block = observer_prohibited(); + + return profile_sidebar(\App::$profile, $block, true, true); + } + +} + diff --git a/Zotlabs/Widget/Sitesearch.php b/Zotlabs/Widget/Sitesearch.php new file mode 100644 index 000000000..b3a25d76a --- /dev/null +++ b/Zotlabs/Widget/Sitesearch.php @@ -0,0 +1,38 @@ +<?php + +namespace Zotlabs\Widget; + + +class Sitesearch { + + function widget($arr) { + + $search = ((x($_GET,'search')) ? $_GET['search'] : ''); + + $srchurl = \App::$query_string; + + $srchurl = rtrim(preg_replace('/search\=[^\&].*?(\&|$)/is','',$srchurl),'&'); + $srchurl = rtrim(preg_replace('/submit\=[^\&].*?(\&|$)/is','',$srchurl),'&'); + $srchurl = str_replace(array('?f=','&f='),array('',''),$srchurl); + + + $hasq = ((strpos($srchurl,'?') !== false) ? true : false); + $hasamp = ((strpos($srchurl,'&') !== false) ? true : false); + + if(($hasamp) && (! $hasq)) + $srchurl = substr($srchurl,0,strpos($srchurl,'&')) . '?f=&' . substr($srchurl,strpos($srchurl,'&')+1); + + $o = ''; + + $saved = array(); + + $tpl = get_markup_template("sitesearch.tpl"); + $o = replace_macros($tpl, array( + '$title' => t('Search'), + '$searchbox' => searchbox($search, 'netsearch-box', $srchurl . (($hasq) ? '' : '?f='), false), + '$saved' => $saved, + )); + + return $o; + } +} diff --git a/Zotlabs/Widget/Suggestedchats.php b/Zotlabs/Widget/Suggestedchats.php new file mode 100644 index 000000000..7df42944d --- /dev/null +++ b/Zotlabs/Widget/Suggestedchats.php @@ -0,0 +1,37 @@ +<?php + +namespace Zotlabs\Widget; + +class Suggestedchats { + + function widget($arr) { + + if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) + return ''; + + // There are reports that this tool does not ever remove chatrooms on dead sites, + // and also will happily link to private chats which you cannot enter. + // For those reasons, it will be disabled until somebody decides it's worth + // fixing and comes up with a plan for doing so. + + return ''; + + // probably should restrict this to your friends, but then the widget will only work + // if you are logged in locally. + + $h = get_observer_hash(); + if(! $h) + return; + $r = q("select xchat_url, xchat_desc, count(xchat_xchan) as total from xchat group by xchat_url, xchat_desc order by total desc, xchat_desc limit 24"); + if($r) { + for($x = 0; $x < count($r); $x ++) { + $r[$x]['xchat_url'] = zid($r[$x]['xchat_url']); + } + } + return replace_macros(get_markup_template('bookmarkedchats.tpl'),array( + '$header' => t('Suggested Chatrooms'), + '$rooms' => $r + )); + } +} + diff --git a/Zotlabs/Widget/Suggestions.php b/Zotlabs/Widget/Suggestions.php new file mode 100644 index 000000000..5fb3d3e8b --- /dev/null +++ b/Zotlabs/Widget/Suggestions.php @@ -0,0 +1,58 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/socgraph.php'); + + +class Suggestions { + + function widget($arr) { + + if((! local_channel()) || (! feature_enabled(local_channel(),'suggest'))) + return ''; + + + $r = suggestion_query(local_channel(),get_observer_hash(),0,20); + + if(! $r) { + return; + } + + $arr = array(); + + // Get two random entries from the top 20 returned. + // We'll grab the first one and the one immediately following. + // This will throw some entropy intot he situation so you won't + // be looking at the same two mug shots every time the widget runs + + $index = ((count($r) > 2) ? mt_rand(0,count($r) - 2) : 0); + + for($x = $index; $x <= ($index+1); $x ++) { + $rr = $r[$x]; + if(! $rr['xchan_url']) + break; + + $connlnk = z_root() . '/follow/?url=' . $rr['xchan_addr']; + + $arr[] = array( + 'url' => chanlink_url($rr['xchan_url']), + 'profile' => $rr['xchan_url'], + 'name' => $rr['xchan_name'], + 'photo' => $rr['xchan_photo_m'], + 'ignlnk' => z_root() . '/directory?ignore=' . $rr['xchan_hash'], + 'conntxt' => t('Connect'), + 'connlnk' => $connlnk, + 'ignore' => t('Ignore/Hide') + ); + } + + $o = replace_macros(get_markup_template('suggest_widget.tpl'),array( + '$title' => t('Suggestions'), + '$more' => t('See more...'), + '$entries' => $arr + )); + + return $o; + } +} diff --git a/Zotlabs/Widget/Tagcloud.php b/Zotlabs/Widget/Tagcloud.php new file mode 100644 index 000000000..cf7a4932e --- /dev/null +++ b/Zotlabs/Widget/Tagcloud.php @@ -0,0 +1,33 @@ +<?php + +namespace Zotlabs\Widget; + +// @FIXME The problem with this widget is that we don't have a search function for webpages +// that we can send the links to. Then we should also provide an option to search webpages +// and conversations. + +class Tagcloud { + + function widget($args) { + + $o = ''; + $uid = \App::$profile_uid; + $count = ((x($args,'count')) ? intval($args['count']) : 24); + $flags = 0; + $type = TERM_CATEGORY; + + // @FIXME there exists no $authors variable + $r = tagadelic($uid, $count, $authors, $owner, $flags, ITEM_TYPE_WEBPAGE, $type); + + // @FIXME this should use a template + + if($r) { + $o = '<div class="tagblock widget"><h3>' . t('Categories') . '</h3><div class="tags" align="center">'; + foreach($r as $rv) { + $o .= '<span class="tag' . $rv[2] . '">' . $rv[0] .' </span> ' . "\r\n"; + } + $o .= '</div></div>'; + } + return $o; + } +} diff --git a/Zotlabs/Widget/Tagcloud_wall.php b/Zotlabs/Widget/Tagcloud_wall.php new file mode 100644 index 000000000..7cff6ce09 --- /dev/null +++ b/Zotlabs/Widget/Tagcloud_wall.php @@ -0,0 +1,20 @@ +<?php + +namespace Zotlabs\Widget; + +class Tagcloud_wall { + + function widget($arr) { + + if((! \App::$profile['profile_uid']) || (! \App::$profile['channel_hash'])) + return ''; + if(! perm_is_allowed(\App::$profile['profile_uid'], get_observer_hash(), 'view_stream')) + return ''; + + $limit = ((array_key_exists('limit', $arr)) ? intval($arr['limit']) : 50); + if(feature_enabled(\App::$profile['profile_uid'], 'tagadelic')) + return wtagblock(\App::$profile['profile_uid'], $limit, '', \App::$profile['channel_hash'], 'wall'); + + return ''; + } +} diff --git a/Zotlabs/Widget/Tasklist.php b/Zotlabs/Widget/Tasklist.php new file mode 100644 index 000000000..6f7a8aaed --- /dev/null +++ b/Zotlabs/Widget/Tasklist.php @@ -0,0 +1,30 @@ +<?php + +namespace Zotlabs\Widget; + +require_once('include/event.php'); + +class Tasklist { + + function widget($arr) { + + 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();}); } + function tasksFetch() { + $.get("tasks/fetch" + ((tasksShowAll) ? "/all" : ""), function(data) { + $(".tasklist-tasks").html(data.html); + }); + } + </script>'; + + $o .= '<div class="widget">' . '<h3>' . t('Tasks') . '</h3><div class="tasklist-tasks">'; + $o .= '</div><form id="tasklist-new-form" action="" ><input id="tasklist-new-summary" type="text" name="summary" value="" /></form>'; + $o .= '</div>'; + return $o; + + } +} + diff --git a/Zotlabs/Widget/Vcard.php b/Zotlabs/Widget/Vcard.php new file mode 100644 index 000000000..cab05dfdd --- /dev/null +++ b/Zotlabs/Widget/Vcard.php @@ -0,0 +1,12 @@ +<?php + +namespace Zotlabs\Widget; + +class Vcard { + + function widget($arr) { + return vcard_from_xchan('', \App::get_observer()); + } + +} + diff --git a/Zotlabs/Widget/Website_portation_tools.php b/Zotlabs/Widget/Website_portation_tools.php new file mode 100644 index 000000000..1cf3bb78a --- /dev/null +++ b/Zotlabs/Widget/Website_portation_tools.php @@ -0,0 +1,22 @@ +<?php + +namespace Zotlabs\Widget; + + +class Website_portation_tools { + + function widget($arr) { + + // mod menu doesn't load a profile. For any modules which load a profile, check it. + // otherwise local_channel() is sufficient for permissions. + + if(\App::$profile['profile_uid']) + if((\App::$profile['profile_uid'] != local_channel()) && (! \App::$is_sys)) + return ''; + + if(! local_channel()) + return ''; + + return website_portation_tools(); + } +} diff --git a/Zotlabs/Widget/Wiki_list.php b/Zotlabs/Widget/Wiki_list.php new file mode 100644 index 000000000..62f32dbf0 --- /dev/null +++ b/Zotlabs/Widget/Wiki_list.php @@ -0,0 +1,23 @@ +<?php + +namespace Zotlabs\Widget; + +class Wiki_list { + + function widget($arr) { + + $channel = channelx_by_n(\App::$profile_uid); + + $wikis = \Zotlabs\Lib\NativeWiki::listwikis($channel,get_observer_hash()); + + if($wikis) { + return replace_macros(get_markup_template('wikilist_widget.tpl'), array( + '$header' => t('Wiki List'), + '$channel' => $channel['channel_address'], + '$wikis' => $wikis['wikis'] + )); + } + return ''; + } + +} diff --git a/Zotlabs/Widget/Wiki_page_history.php b/Zotlabs/Widget/Wiki_page_history.php new file mode 100644 index 000000000..dcec9a037 --- /dev/null +++ b/Zotlabs/Widget/Wiki_page_history.php @@ -0,0 +1,27 @@ +<?php + +namespace Zotlabs\Widget; + +class Wiki_page_history { + + function widget($arr) { + + $pageUrlName = ((array_key_exists('pageUrlName', $arr)) ? $arr['pageUrlName'] : ''); + $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : ''); + + $pageHistory = \Zotlabs\Lib\NativeWikiPage::page_history([ + 'channel_id' => \App::$profile_uid, + 'observer_hash' => get_observer_hash(), + 'resource_id' => $resource_id, + 'pageUrlName' => $pageUrlName + ]); + + return replace_macros(get_markup_template('nwiki_page_history.tpl'), array( + '$pageHistory' => $pageHistory['history'], + '$permsWrite' => $arr['permsWrite'], + '$name_lbl' => t('Name'), + '$msg_label' => t('Message','wiki_history') + )); + + } +} diff --git a/Zotlabs/Widget/Wiki_pages.php b/Zotlabs/Widget/Wiki_pages.php new file mode 100644 index 000000000..f992b3f93 --- /dev/null +++ b/Zotlabs/Widget/Wiki_pages.php @@ -0,0 +1,66 @@ +<?php + +namespace Zotlabs\Widget; + + +class Wiki_pages { + + function widget($arr) { + + $channelname = ((array_key_exists('channel',$arr)) ? $arr['channel'] : ''); + $c = channelx_by_nick($channelname); + + if(! $c) + $c = \App::get_channel(); + + if(! $c) + return ''; + + $wikiname = ''; + if(array_key_exists('refresh', $arr)) { + $not_refresh = (($arr['refresh']=== true) ? false : true); + } + else { + $not_refresh = true; + } + + $pages = array(); + if(! array_key_exists('resource_id', $arr)) { + $hide = true; + } + else { + $p = \Zotlabs\Lib\NativeWikiPage::page_list($c['channel_id'],get_observer_hash(),$arr['resource_id']); + + if($p['pages']) { + $pages = $p['pages']; + $w = $p['wiki']; + // Wiki item record is $w['wiki'] + $wikiname = $w['urlName']; + if (!$wikiname) { + $wikiname = ''; + } + } + } + + + $can_create = perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'write_wiki'); + + $can_delete = ((local_channel() && (local_channel() == \App::$profile['uid'])) ? true : false); + + return replace_macros(get_markup_template('wiki_page_list.tpl'), array( + '$hide' => $hide, + '$resource_id' => $arr['resource_id'], + '$not_refresh' => $not_refresh, + '$header' => t('Wiki Pages'), + '$channel' => $channelname, + '$wikiname' => $wikiname, + '$pages' => $pages, + '$canadd' => $can_create, + '$candel' => $can_delete, + '$addnew' => t('Add new page'), + '$pageName' => array('pageName', t('Page name')), + )); + } +} + + diff --git a/Zotlabs/Widget/Zcard.php b/Zotlabs/Widget/Zcard.php new file mode 100644 index 000000000..12e53eaab --- /dev/null +++ b/Zotlabs/Widget/Zcard.php @@ -0,0 +1,11 @@ +<?php + +namespace Zotlabs\Widget; + +class Zcard { + + function widget($args) { + $channel = channelx_by_n(\App::$profile_uid); + return get_zcard($channel,get_observer_hash(),array('width' => 875)); + } +} diff --git a/Zotlabs/Zot/Finger.php b/Zotlabs/Zot/Finger.php index 7e0f5fb7c..9871b5bbd 100644 --- a/Zotlabs/Zot/Finger.php +++ b/Zotlabs/Zot/Finger.php @@ -123,9 +123,7 @@ class Finger { } else { logger('No signed token from ' . $url . $rhs, LOGGER_NORMAL, LOG_WARNING); - // after 2017-01-01 this will be a hard error unless you over-ride it. - if((time() > 1483228800) && (! get_config('system', 'allow_unsigned_zotfinger'))) - return $ret; + return $ret; } } diff --git a/Zotlabs/Zot/Receiver.php b/Zotlabs/Zot/Receiver.php index 71d57eb35..0050a2559 100644 --- a/Zotlabs/Zot/Receiver.php +++ b/Zotlabs/Zot/Receiver.php @@ -138,7 +138,6 @@ class Receiver { * This packet is optionally encrypted, which we will discover if the json has an 'iv' element. * $contents => array( 'alg' => 'aes256cbc', 'iv' => initialisation vector, 'key' => decryption key, 'data' => encrypted data); * $contents->iv and $contents->key are random strings encrypted with this site's RSA public key and then base64url encoded. - * Currently only 'aes256cbc' is used, but this is extensible should that algorithm prove inadequate. * * Once decrypted, one will find the normal json_encoded zot message packet. * @@ -156,7 +155,8 @@ class Receiver { * }, * "recipients": { optional recipient array }, * "callback":"\/post", - * "version":1, + * "version":"1.2", + * "encryption":["aes256cbc"], * "secret":"1eaa...", * "secret_sig": "df89025470fac8..." * } |