Merge branch 'zap'

This commit is contained in:
zotlabs 2018-08-20 22:26:00 -07:00
commit 9f979cab89
19 changed files with 777 additions and 185 deletions

View file

@ -313,7 +313,7 @@ class ActivityStreams {
}
}
}
if($first && is_array($x) && && array_key_exists(0,$x)) {
if($first && is_array($x) && array_key_exists(0,$x)) {
return $x[0];
}

View file

@ -195,7 +195,6 @@ class ThreadStream {
$item->set_commentable(false);
}
require_once('include/channel.php');
$item->set_conversation($this);
$this->threads[] = $item;

View file

@ -7,18 +7,22 @@ use Zotlabs\Lib\Activity;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Web\HTTPSig;
require_once('include/contact_widgets.php');
require_once("include/bbcode.php");
use App;
use Zotlabs\Web\Controller;
use Zotlabs\Lib\PermissionDescription;
require_once('include/items.php');
require_once('include/security.php');
require_once('include/conversation.php');
require_once('include/acl_selectors.php');
require_once('include/permissions.php');
/**
* @brief Channel Controller
*
*/
class Channel extends \Zotlabs\Web\Controller {
class Channel extends Controller {
function init() {
@ -30,7 +34,7 @@ class Channel extends \Zotlabs\Web\Controller {
$which = argv(1);
if(! $which) {
if(local_channel()) {
$channel = \App::get_channel();
$channel = App::get_channel();
if($channel && $channel['channel_address'])
$which = $channel['channel_address'];
}
@ -41,7 +45,7 @@ class Channel extends \Zotlabs\Web\Controller {
}
$profile = 0;
$channel = \App::get_channel();
$channel = App::get_channel();
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
$which = $channel['channel_address'];
@ -117,8 +121,6 @@ class Channel extends \Zotlabs\Web\Controller {
if($load)
$_SESSION['loadtime'] = datetime_convert();
$checkjs = new \Zotlabs\Web\CheckJS(1);
$category = $datequery = $datequery2 = '';
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
@ -149,22 +151,22 @@ class Channel extends \Zotlabs\Web\Controller {
if($update) {
// Ensure we've got a profile owner if updating.
\App::$profile['profile_uid'] = \App::$profile_uid = $update;
App::$profile['profile_uid'] = App::$profile_uid = $update;
}
$is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false);
$is_owner = (((local_channel()) && (App::$profile['profile_uid'] == local_channel())) ? true : false);
$channel = \App::get_channel();
$observer = \App::get_observer();
$channel = App::get_channel();
$observer = App::get_observer();
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
$perms = get_all_perms(\App::$profile['profile_uid'],$ob_hash);
$perms = get_all_perms(App::$profile['profile_uid'],$ob_hash);
if(! $perms['view_stream']) {
// We may want to make the target of this redirect configurable
if($perms['view_profile']) {
notice( t('Insufficient permissions. Request redirected to profile page.') . EOL);
goaway (z_root() . "/profile/" . \App::$profile['channel_address']);
goaway (z_root() . "/profile/" . App::$profile['channel_address']);
}
notice( t('Permission denied.') . EOL);
return;
@ -175,7 +177,7 @@ class Channel extends \Zotlabs\Web\Controller {
nav_set_selected('Channel Home');
$static = channel_manual_conv_update(\App::$profile['profile_uid']);
$static = channel_manual_conv_update(App::$profile['profile_uid']);
// search terms header
if($search) {
@ -201,16 +203,16 @@ class Channel extends \Zotlabs\Web\Controller {
$x = array(
'is_owner' => $is_owner,
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(\App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
'default_location' => (($is_owner) ? \App::$profile['channel_location'] : ''),
'nickname' => \App::$profile['channel_address'],
'lockstate' => (((strlen(\App::$profile['channel_allow_cid'])) || (strlen(\App::$profile['channel_allow_gid'])) || (strlen(\App::$profile['channel_deny_cid'])) || (strlen(\App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
'default_location' => (($is_owner) ? App::$profile['channel_location'] : ''),
'nickname' => App::$profile['channel_address'],
'lockstate' => (((strlen(App::$profile['channel_allow_cid'])) || (strlen(App::$profile['channel_allow_gid'])) || (strlen(App::$profile['channel_deny_cid'])) || (strlen(App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
'acl' => (($is_owner) ? populate_acl($channel_acl,true, PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
'permissions' => $channel_acl,
'showacl' => (($is_owner) ? 'yes' : ''),
'bang' => '',
'visitor' => (($is_owner || $observer) ? true : false),
'profile_uid' => \App::$profile['profile_uid'],
'profile_uid' => App::$profile['profile_uid'],
'editor_autocomplete' => true,
'bbco_autocomplete' => 'bbcode',
'bbcode' => true,
@ -230,14 +232,14 @@ class Channel extends \Zotlabs\Web\Controller {
$item_normal = item_normal();
$item_normal_update = item_normal_update();
$sql_extra = item_permissions_sql(\App::$profile['profile_uid']);
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
if(get_pconfig(\App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid))
if(get_pconfig(App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid))
$page_mode = 'list';
else
$page_mode = 'client';
$abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " ";
$abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
@ -257,7 +259,7 @@ class Channel extends \Zotlabs\Web\Controller {
head_add_link([
'rel' => 'alternate',
'type' => 'application/json+oembed',
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
'title' => 'oembed'
]);
@ -275,7 +277,7 @@ class Channel extends \Zotlabs\Web\Controller {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update
AND item_wall = 1 $simple_update $sql_extra limit 1",
dbesc($mid . '%'),
intval(\App::$profile['profile_uid'])
intval(App::$profile['profile_uid'])
);
$_SESSION['loadtime'] = datetime_convert();
}
@ -287,7 +289,7 @@ class Channel extends \Zotlabs\Web\Controller {
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra
ORDER BY created DESC",
intval(\App::$profile['profile_uid'])
intval(App::$profile['profile_uid'])
);
$_SESSION['loadtime'] = datetime_convert();
}
@ -296,10 +298,10 @@ class Channel extends \Zotlabs\Web\Controller {
else {
if(x($category)) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
}
if(x($hashtags)) {
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
}
if($datequery) {
@ -321,15 +323,15 @@ class Channel extends \Zotlabs\Web\Controller {
$itemspage = get_pconfig(local_channel(),'system','itemspage');
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
if($load || ($checkjs->disabled())) {
if((! $update) || ($load)) {
if($mid) {
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
AND item_wall = 1 $sql_extra limit 1",
dbesc($mid . '%'),
intval(\App::$profile['profile_uid'])
intval(App::$profile['profile_uid'])
);
if (! $r) {
notice( t('Permission denied.') . EOL);
@ -343,7 +345,7 @@ class Channel extends \Zotlabs\Web\Controller {
AND item.item_wall = 1 AND item.item_thread_top = 1
$sql_extra $sql_extra2
ORDER BY $ordering DESC $pager_sql ",
intval(\App::$profile['profile_uid'])
intval(App::$profile['profile_uid'])
);
}
}
@ -360,7 +362,7 @@ class Channel extends \Zotlabs\Web\Controller {
WHERE item.uid = %d $item_normal
AND item.parent IN ( %s )
$sql_extra ",
intval(\App::$profile['profile_uid']),
intval(App::$profile['profile_uid']),
dbesc($parents_str)
);
@ -383,19 +385,19 @@ class Channel extends \Zotlabs\Web\Controller {
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
// because browser prefetching might change it on us. We have to deliver it with the page.
$maxheight = get_pconfig(\App::$profile['profile_uid'],'system','channel_divmore_height');
$maxheight = get_pconfig(App::$profile['profile_uid'],'system','channel_divmore_height');
if(! $maxheight)
$maxheight = 400;
$o .= '<div id="live-channel"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . \App::$profile['profile_uid']
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page']
$o .= "<script> var profile_uid = " . App::$profile['profile_uid']
. "; var netargs = '?f='; var profile_page = " . App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'channel',
'$uid' => ((\App::$profile['profile_uid']) ? \App::$profile['profile_uid'] : '0'),
'$uid' => ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : '0'),
'$gid' => '0',
'$cid' => '0',
'$cmin' => '(-1)',
@ -408,7 +410,7 @@ class Channel extends \Zotlabs\Web\Controller {
'$wall' => '1',
'$fh' => '0',
'$static' => $static,
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => $search,
'$xchan' => '',
'$order' => $order,
@ -459,17 +461,19 @@ class Channel extends \Zotlabs\Web\Controller {
$mode = (($search) ? 'search' : 'channel');
if($checkjs->disabled()) {
$o .= conversation($items,$mode,$update,'traditional');
}
else {
if($update) {
$o .= conversation($items,$mode,$update,$page_mode);
}
if((! $update) || ($checkjs->disabled())) {
else {
$o .= '<noscript>';
$o .= conversation($items,$mode,$update,'traditional');
$o .= alt_pager(count($items));
$o .= '</noscript>';
$o .= conversation($items,$mode,$update,$page_mode);
if ($mid && $items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
App::$page['title'] = $items[0]['title'] . " - " . App::$page['title'];
}
if($mid)

View file

@ -20,8 +20,6 @@ class Display extends \Zotlabs\Web\Controller {
$module_format = 'html';
}
$checkjs = new \Zotlabs\Web\CheckJS(1);
if($load)
$_SESSION['loadtime'] = datetime_convert();
@ -252,53 +250,44 @@ class Display extends \Zotlabs\Web\Controller {
$sql_extra = public_permissions_sql($observer_hash);
if(($update && $load) || ($checkjs->disabled()) || ($module_format !== 'html')) {
if((! $update) || ($load)) {
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start']));
$r = null;
if($load || ($checkjs->disabled()) || ($module_format !== 'html')) {
require_once('include/channel.php');
$sys = get_sys_channel();
$sysid = $sys['channel_id'];
$r = null;
require_once('include/channel.php');
$sys = get_sys_channel();
$sysid = $sys['channel_id'];
if(local_channel()) {
$r = q("SELECT item.id as item_id from item
WHERE uid = %d
and mid = '%s'
$item_normal
limit 1",
intval(local_channel()),
dbesc($target_item['parent_mid'])
);
if($r) {
$updateable = true;
}
if(local_channel()) {
$r = q("SELECT item.id as item_id from item WHERE uid = %d and mid = '%s' $item_normal limit 1",
intval(local_channel()),
dbesc($target_item['parent_mid'])
);
if($r) {
$updateable = true;
}
}
if(! $r) {
if(! $r) {
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner uid can't match
// in case somebody turned off public access to sys channel content using permissions
// make that content unsearchable by ensuring the owner uid can't match
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
$sysid = 0;
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
$sysid = 0;
$r = q("SELECT item.id as item_id from item
WHERE mid = '%s'
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
AND item.deny_gid = '' AND item_private = 0 )
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
OR uid = %d )
$sql_extra )
$item_normal
limit 1",
dbesc($target_item['parent_mid']),
intval($sysid)
);
}
$r = q("SELECT item.id as item_id from item
WHERE mid = '%s'
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
AND item.deny_gid = '' AND item_private = 0 )
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
OR uid = %d )
$sql_extra )
$item_normal
limit 1",
dbesc($target_item['parent_mid']),
intval($sysid)
);
}
}
@ -372,14 +361,19 @@ class Display extends \Zotlabs\Web\Controller {
case 'html':
if ($checkjs->disabled()) {
$o .= conversation($items, 'display', $update, 'traditional');
if ($items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
}
else {
if ($update) {
$o .= conversation($items, 'display', $update, 'client');
}
else {
$o .= '<noscript>';
$o .= conversation($items, 'display', $update, 'traditional');
$o .= '</noscript>';
if ($items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
$o .= conversation($items, 'display', $update, 'client');
}
break;
@ -434,7 +428,7 @@ class Display extends \Zotlabs\Web\Controller {
$o .= '<div id="content-complete"></div>';
if((($update && $load) || $checkjs->disabled()) && (! $items)) {
if(((! $update) || ($load)) && (! $items)) {
$r = q("SELECT id, item_deleted FROM item WHERE mid = '%s' LIMIT 1",
dbesc($item_hash)

View file

@ -1,9 +1,9 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\Group;
use Zotlabs\Lib\Apps;
use App;
require_once('include/contact_widgets.php');
require_once('include/conversation.php');
@ -27,8 +27,8 @@ class Network extends \Zotlabs\Web\Controller {
goaway('network' . '?f=&' . $network_options);
}
$channel = \App::get_channel();
\App::$profile_uid = local_channel();
$channel = App::get_channel();
App::$profile_uid = local_channel();
head_set_icon($channel['xchan_photo_s']);
}
@ -36,7 +36,7 @@ class Network extends \Zotlabs\Web\Controller {
function get($update = 0, $load = false) {
if(! local_channel()) {
$_SESSION['return_url'] = \App::$query_string;
$_SESSION['return_url'] = App::$query_string;
return login(false);
}
@ -46,11 +46,11 @@ class Network extends \Zotlabs\Web\Controller {
$_SESSION['loadtime'] = datetime_convert();
}
$arr = array('query' => \App::$query_string);
$arr = array('query' => App::$query_string);
call_hooks('network_content_init', $arr);
$channel = \App::get_channel();
$channel = App::get_channel();
$item_normal = item_normal();
$item_normal_update = item_normal_update();
@ -328,10 +328,10 @@ class Network extends \Zotlabs\Web\Controller {
$o .= '<div id="live-network"></div>' . "\r\n";
$o .= "<script> var profile_uid = " . local_channel()
. "; var profile_page = " . \App::$pager['page']
. "; var profile_page = " . App::$pager['page']
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
'$baseurl' => z_root(),
'$pgtype' => 'network',
'$uid' => ((local_channel()) ? local_channel() : '0'),
@ -348,7 +348,7 @@ class Network extends \Zotlabs\Web\Controller {
'$wall' => '0',
'$static' => $static,
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
'$search' => (($search) ? $search : ''),
'$xchan' => $xchan,
'$order' => $order,
@ -419,8 +419,8 @@ class Network extends \Zotlabs\Web\Controller {
}
else {
$itemspage = get_pconfig(local_channel(),'system','itemspage');
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
}
// cmin and cmax are both -1 when the affinity tool is disabled

View file

@ -64,17 +64,20 @@ class SmartyTemplate implements TemplateEngine {
public function get_intltext_template($file, $root='') {
$lang = \App::$language;
if(file_exists("view/$lang/$file"))
$template_file = "view/$lang/$file";
elseif(file_exists("view/en/$file"))
$template_file = "view/en/$file";
else
$template_file = theme_include($file,$root);
if ($root != '' && substr($root,-1) != '/' ) {
$root .= '/';
}
foreach (Array(
$root."view/$lang/$file",
$root."view/en/$file",
''
) as $template_file) {
if (is_file($template_file)) { break; }
}
if ($template_file=='') {$template_file = theme_include($file,$root);}
if($template_file) {
$template = new SmartyInterface();
$template->filename = $template_file;
return $template;
}
return "";

View file

@ -9,9 +9,8 @@ class _1218 {
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r1 = q("ALTER TABLE hubloc add hubloc_id_url text NOT NULL");
$r2 = q("create index \"hubloc_id_url\" on hubloc (\"hubloc_id_url\")");
$r1 = q("ALTER TABLE hubloc add hubloc_site_id text NOT NULL");
$r2 = q("create index \"hubloc_site_id\" on hubloc (\"hubloc_site_id\")");
$r3 = q("ALTER TABLE hubloc add hubloc_site_id text NOT NULL");
$r4 = q("create index \"hubloc_site_id\" on hubloc (\"hubloc_site_id\")");
$r = $r1 && $r2 && $r3 && $r4;
}
@ -20,7 +19,6 @@ class _1218 {
$r1 = q("ALTER TABLE hubloc add hubloc_id_url varchar(191) NOT NULL, ADD INDEX hubloc_id_url (hubloc_id_url)");
$r2 = q("ALTER TABLE hubloc add hubloc_site_id varchar(191) NOT NULL, ADD INDEX hubloc_site_id (hubloc_site_id)");
$r = $r1 && $r2;
}

View file

@ -20,6 +20,16 @@ class Cover_photo {
if(! $channel_id)
return '';
// only show cover photos once per login session
if(array_key_exists('channels_visited',$_SESSION) && is_array($_SESSION['channels_visited']) && in_array($channel_id,$_SESSION['channels_visited'])) {
return EMPTY_STR;
}
if(! array_key_exists('channels_visited',$_SESSION)) {
$_SESSION['channels_visited'] = [];
}
$_SESSION['channels_visited'][] = $channel_id;
$channel = channelx_by_n($channel_id);
if(array_key_exists('style', $arr) && isset($arr['style']))

507
Zotlabs/Zot6/HTTPSig.php Normal file
View file

@ -0,0 +1,507 @@
<?php
namespace Zotlabs\Zot6;
use Zotlabs\Lib\ActivityStreams;
use Zotlabs\Lib\Webfinger;
use Zotlabs\Web\HTTPHeaders;
/**
* @brief Implements HTTP Signatures per draft-cavage-http-signatures-10.
*
* @see https://tools.ietf.org/html/draft-cavage-http-signatures-10
*/
class HTTPSig {
/**
* @brief RFC5843
*
* @see https://tools.ietf.org/html/rfc5843
*
* @param string $body The value to create the digest for
* @param string $alg hash algorithm (one of 'sha256','sha512')
* @return string The generated digest header string for $body
*/
static function generate_digest_header($body,$alg = 'sha256') {
$digest = base64_encode(hash($alg, $body, true));
switch($alg) {
case 'sha512':
return 'SHA-512=' . $digest;
case 'sha256':
default:
return 'SHA-256=' . $digest;
break;
}
}
static function find_headers($data,&$body) {
// decide if $data arrived via controller submission or curl
if(is_array($data) && $data['header']) {
if(! $data['success'])
return [];
$h = new HTTPHeaders($data['header']);
$headers = $h->fetcharr();
$body = $data['body'];
}
else {
$headers = [];
$headers['(request-target)'] = strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI'];
$headers['content-type'] = $_SERVER['CONTENT_TYPE'];
foreach($_SERVER as $k => $v) {
if(strpos($k,'HTTP_') === 0) {
$field = str_replace('_','-',strtolower(substr($k,5)));
$headers[$field] = $v;
}
}
}
//logger('SERVER: ' . print_r($_SERVER,true), LOGGER_ALL);
//logger('headers: ' . print_r($headers,true), LOGGER_ALL);
return $headers;
}
// See draft-cavage-http-signatures-10
static function verify($data,$key = '') {
$body = $data;
$headers = null;
$result = [
'signer' => '',
'portable_id' => '',
'header_signed' => false,
'header_valid' => false,
'content_signed' => false,
'content_valid' => false
];
$headers = self::find_headers($data,$body);
if(! $headers)
return $result;
$sig_block = null;
if(array_key_exists('signature',$headers)) {
$sig_block = self::parse_sigheader($headers['signature']);
}
elseif(array_key_exists('authorization',$headers)) {
$sig_block = self::parse_sigheader($headers['authorization']);
}
if(! $sig_block) {
logger('no signature provided.', LOGGER_DEBUG);
return $result;
}
// Warning: This log statement includes binary data
// logger('sig_block: ' . print_r($sig_block,true), LOGGER_DATA);
$result['header_signed'] = true;
$signed_headers = $sig_block['headers'];
if(! $signed_headers)
$signed_headers = [ 'date' ];
$signed_data = '';
foreach($signed_headers as $h) {
if(array_key_exists($h,$headers)) {
$signed_data .= $h . ': ' . $headers[$h] . "\n";
}
}
$signed_data = rtrim($signed_data,"\n");
$algorithm = null;
if($sig_block['algorithm'] === 'rsa-sha256') {
$algorithm = 'sha256';
}
if($sig_block['algorithm'] === 'rsa-sha512') {
$algorithm = 'sha512';
}
if(! array_key_exists('keyId',$sig_block))
return $result;
$result['signer'] = $sig_block['keyId'];
$key = self::get_key($key,$result['signer']);
if(! ($key && $key['public_key'])) {
return $result;
}
$x = rsa_verify($signed_data,$sig_block['signature'],$key['public_key'],$algorithm);
logger('verified: ' . $x, LOGGER_DEBUG);
if(! $x)
return $result;
$result['portable_id'] = $key['portable_id'];
$result['header_valid'] = true;
if(in_array('digest',$signed_headers)) {
$result['content_signed'] = true;
$digest = explode('=', $headers['digest'], 2);
if($digest[0] === 'SHA-256')
$hashalg = 'sha256';
if($digest[0] === 'SHA-512')
$hashalg = 'sha512';
if(base64_encode(hash($hashalg,$body,true)) === $digest[1]) {
$result['content_valid'] = true;
}
logger('Content_Valid: ' . (($result['content_valid']) ? 'true' : 'false'));
}
return $result;
}
static function get_key($key,$id) {
if($key) {
if(function_exists($key)) {
return $key($id);
}
return [ 'public_key' => $key ];
}
$key = self::get_webfinger_key($id);
if(! $key) {
$key = self::get_activitystreams_key($id);
}
return $key;
}
function convertKey($key) {
if(strstr($key,'RSA ')) {
return rsatopem($key);
}
elseif(substr($key,0,5) === 'data:') {
return convert_salmon_key($key);
}
else {
return $key;
}
}
/**
* @brief
*
* @param string $id
* @return boolean|string
* false if no pub key found, otherwise return the pub key
*/
function get_activitystreams_key($id) {
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' limit 1",
dbesc(str_replace('acct:','',$id)),
dbesc($id)
);
if($x && $x[0]['xchan_pubkey']) {
return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ];
}
$r = ActivityStreams::fetch_property($id);
if($r) {
if(array_key_exists('publicKey',$j) && array_key_exists('publicKeyPem',$j['publicKey']) && array_key_exists('id',$j['publicKey'])) {
if($j['publicKey']['id'] === $id || $j['id'] === $id) {
return [ 'public_key' => self::convertKey($j['publicKey']['publicKeyPem']), 'portable_id' => '', 'hubloc' => [] ];
}
}
}
return false;
}
function get_webfinger_key($id) {
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' limit 1",
dbesc(str_replace('acct:','',$id)),
dbesc($id)
);
if($x && $x[0]['xchan_pubkey']) {
return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ];
}
$wf = Webfinger::exec($id);
$key = [ 'portable_id' => '', 'public_key' => '', 'hubloc' => [] ];
if($wf) {
if(array_key_exists('properties',$wf) && array_key_exists('https://w3id.org/security/v1#publicKeyPem',$wf['properties'])) {
$key['public_key'] = self::convertKey($wf['properties']['https://w3id.org/security/v1#publicKeyPem']);
}
if(array_key_exists('links', $wf) && is_array($wf['links'])) {
foreach($wf['links'] as $l) {
if(! (is_array($l) && array_key_exists('rel',$l))) {
continue;
}
if($l['rel'] === 'magic-public-key' && array_key_exists('href',$l) && $key['public_key'] === EMPTY_STR) {
$key['public_key'] = self::convertKey($l['href']);
}
}
}
}
return (($key['public_key']) ? $key : false);
}
function get_zotfinger_key($id) {
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' limit 1",
dbesc(str_replace('acct:','',$id)),
dbesc($id)
);
if($x && $x[0]['xchan_pubkey']) {
return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ];
}
$wf = Webfinger::exec($id);
$key = [ 'portable_id' => '', 'public_key' => '', 'hubloc' => [] ];
if($wf) {
if(array_key_exists('properties',$wf) && array_key_exists('https://w3id.org/security/v1#publicKeyPem',$wf['properties'])) {
$key['public_key'] = self::convertKey($wf['properties']['https://w3id.org/security/v1#publicKeyPem']);
}
if(array_key_exists('links', $wf) && is_array($wf['links'])) {
foreach($wf['links'] as $l) {
if(! (is_array($l) && array_key_exists('rel',$l))) {
continue;
}
if($l['rel'] === 'http://purl.org/zot/protocol/6.0' && array_key_exists('href',$l) && $l['href'] !== EMPTY_STR) {
$z = \Zotlabs\Lib\Zotfinger::exec($l['href']);
if($z) {
$i = Zotlabs\Lib\Libzot::import_xchan($z['data']);
if($i['success']) {
$key['portable_id'] = $i['hash'];
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
dbesc($l['href'])
);
if($x) {
$key['hubloc'] = $x[0];
}
}
}
}
if($l['rel'] === 'magic-public-key' && array_key_exists('href',$l) && $key['public_key'] === EMPTY_STR) {
$key['public_key'] = self::convertKey($l['href']);
}
}
}
}
return (($key['public_key']) ? $key : false);
}
/**
* @brief
*
* @param array $head
* @param string $prvkey
* @param string $keyid (optional, default '')
* @param boolean $auth (optional, default false)
* @param string $alg (optional, default 'sha256')
* @param array $encryption [ 'key', 'algorithm' ] or false
* @return array
*/
static function create_sig($head, $prvkey, $keyid = EMPTY_STR, $auth = false, $alg = 'sha256', $encryption = false ) {
$return_headers = [];
if($alg === 'sha256') {
$algorithm = 'rsa-sha256';
}
if($alg === 'sha512') {
$algorithm = 'rsa-sha512';
}
$x = self::sign($head,$prvkey,$alg);
$headerval = 'keyId="' . $keyid . '",algorithm="' . $algorithm . '",headers="' . $x['headers'] . '",signature="' . $x['signature'] . '"';
if($encryption) {
$x = crypto_encapsulate($headerval,$encryption['key'],$encryption['algorithm']);
if(is_array($x)) {
$headerval = 'iv="' . $x['iv'] . '",key="' . $x['key'] . '",alg="' . $x['alg'] . '",data="' . $x['data'] . '"';
}
}
if($auth) {
$sighead = 'Authorization: Signature ' . $headerval;
}
else {
$sighead = 'Signature: ' . $headerval;
}
if($head) {
foreach($head as $k => $v) {
// strip the request-target virtual header from the output headers
if($k === '(request-target)') {
continue;
}
$return_headers[] = $k . ': ' . $v;
}
}
$return_headers[] = $sighead;
return $return_headers;
}
/**
* @brief set headers
*
* @param array $headers
* @return void
*/
static function set_headers($headers) {
if($headers && is_array($headers)) {
foreach($headers as $h) {
header($h);
}
}
}
/**
* @brief
*
* @param array $head
* @param string $prvkey
* @param string $alg (optional) default 'sha256'
* @return array
*/
static function sign($head, $prvkey, $alg = 'sha256') {
$ret = [];
$headers = '';
$fields = '';
if($head) {
foreach($head as $k => $v) {
$headers .= strtolower($k) . ': ' . trim($v) . "\n";
if($fields)
$fields .= ' ';
$fields .= strtolower($k);
}
// strip the trailing linefeed
$headers = rtrim($headers,"\n");
}
$sig = base64_encode(rsa_sign($headers,$prvkey,$alg));
$ret['headers'] = $fields;
$ret['signature'] = $sig;
return $ret;
}
/**
* @brief
*
* @param string $header
* @return array associate array with
* - \e string \b keyID
* - \e string \b algorithm
* - \e array \b headers
* - \e string \b signature
*/
static function parse_sigheader($header) {
$ret = [];
$matches = [];
// if the header is encrypted, decrypt with (default) site private key and continue
if(preg_match('/iv="(.*?)"/ism',$header,$matches))
$header = self::decrypt_sigheader($header);
if(preg_match('/keyId="(.*?)"/ism',$header,$matches))
$ret['keyId'] = $matches[1];
if(preg_match('/algorithm="(.*?)"/ism',$header,$matches))
$ret['algorithm'] = $matches[1];
if(preg_match('/headers="(.*?)"/ism',$header,$matches))
$ret['headers'] = explode(' ', $matches[1]);
if(preg_match('/signature="(.*?)"/ism',$header,$matches))
$ret['signature'] = base64_decode(preg_replace('/\s+/','',$matches[1]));
if(($ret['signature']) && ($ret['algorithm']) && (! $ret['headers']))
$ret['headers'] = [ 'date' ];
return $ret;
}
/**
* @brief
*
* @param string $header
* @param string $prvkey (optional), if not set use site private key
* @return array|string associative array, empty string if failue
* - \e string \b iv
* - \e string \b key
* - \e string \b alg
* - \e string \b data
*/
static function decrypt_sigheader($header, $prvkey = null) {
$iv = $key = $alg = $data = null;
if(! $prvkey) {
$prvkey = get_config('system', 'prvkey');
}
$matches = [];
if(preg_match('/iv="(.*?)"/ism',$header,$matches))
$iv = $matches[1];
if(preg_match('/key="(.*?)"/ism',$header,$matches))
$key = $matches[1];
if(preg_match('/alg="(.*?)"/ism',$header,$matches))
$alg = $matches[1];
if(preg_match('/data="(.*?)"/ism',$header,$matches))
$data = $matches[1];
if($iv && $key && $alg && $data) {
return crypto_unencapsulate([ 'encrypted' => true, 'iv' => $iv, 'key' => $key, 'alg' => $alg, 'data' => $data ] , $prvkey);
}
return '';
}
}

View file

@ -35,7 +35,7 @@ define ( 'PLATFORM_NAME', 'zap' );
define ( 'STD_VERSION', '0.0.1' );
define ( 'ZOT_REVISION', '6.0' );
define ( 'DB_UPDATE_VERSION', 1217 );
define ( 'DB_UPDATE_VERSION', 1218 );
define ( 'PROJECT_BASE', __DIR__ );
@ -694,6 +694,11 @@ class App {
private static $perms = null; // observer permissions
private static $widgets = array(); // widgets for this page
public static $config = array(); // config cache
public static $override_intltext_templates = array();
public static $override_markup_templates = array();
public static $override_templateroot = null;
public static $override_helproot = null;
public static $override_helpfiles = array();
public static $session = null;
public static $groups;
@ -1757,6 +1762,10 @@ function info($s) {
return;
if(! x($_SESSION, 'sysmsg_info'))
$_SESSION['sysmsg_info'] = array();
if(in_array($s, $_SESSION['sysmsg_info']))
return;
if(App::$interactive)
$_SESSION['sysmsg_info'][] = $s;
}

View file

@ -960,12 +960,14 @@ function bbcode($Text, $options = []) {
$Text = preg_replace_callback("/[^\^]\[url\]([$URLSearchString]*)\[\/url\]/ism", 'tryoembed', $Text);
}
}
if (strpos($Text,'[/url]') !== false) {
// $Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
// $Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
$Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
}
if (strpos($Text,'[/zrl]') !== false) {
// $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);
// $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);

View file

@ -2775,4 +2775,4 @@ function anon_identity_init($reqvars) {
function channel_url($channel) {
return (($channel) ? z_root() . '/channel/' . $channel['channel_address'] : z_root());
}
}

View file

@ -2,6 +2,50 @@
use \Michelf\MarkdownExtra;
/**
* @brief
*
* @param string $path
* @return string|unknown
*/
function get_help_fullpath($path,$suffix=null) {
$docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/';
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
// Determine the language and modify the path accordingly
$x = determine_help_language();
$lang = $x['language'];
$url_idx = ($x['from_url'] ? 1 : 0);
// The English translation is at the root of /doc/. Other languages are in
// subfolders named by the language code such as "de", "es", etc.
if($lang !== 'en') {
$langpath = $lang . '/' . $path;
} else {
$langpath = $path;
}
$newpath = (isset(\App::$override_helpfiles[$langpath])) ? \App::$override_helpfiles[$langpath] : $langpath;
$newpath = ($newpath == $langpath) ? $docroot . $newpath : $newpath;
if ($suffix) {
if (file_exists($newpath . $suffix)) {
return $newpath;
}
} elseif (file_exists($newpath . '.md') ||
file_exists($newpath . '.bb') ||
file_exists($newpath . '.html')) {
return $newpath;
}
$newpath = (isset(\App::$override_helpfiles[$path])) ? \App::$override_helpfiles[$path] : null;
$newpath = (!$newpath) ? $docroot.$path : $newpath;
return $newpath;
}
/**
* @brief
*
@ -9,7 +53,6 @@ use \Michelf\MarkdownExtra;
* @return string|unknown
*/
function get_help_content($tocpath = false) {
global $lang;
$doctype = 'markdown';
@ -17,6 +60,8 @@ function get_help_content($tocpath = false) {
$text = '';
$path = (($tocpath !== false) ? $tocpath : '');
$docroot = (\App::$override_helproot) ? \App::$override_helproot : 'doc/';
$docroot = (substr($docroot,-1)!='/') ? $docroot .= '/' : $docroot;
if($tocpath === false && argc() > 1) {
$path = '';
@ -27,8 +72,9 @@ function get_help_content($tocpath = false) {
}
}
if($path) {
if($path) {
$fullpath = get_help_fullpath($path);
$title = basename($path);
if(! $tocpath)
\App::$page['title'] = t('Help:') . ' ' . ucwords(str_replace('-',' ',notags($title)));
@ -39,21 +85,22 @@ function get_help_content($tocpath = false) {
// TODO: This is incompatible with the hierarchical TOC construction
// defined in /Zotlabs/Widget/Helpindex.php.
if($tocpath !== false &&
load_doc_file('doc/' . $path . '.md') === '' &&
load_doc_file('doc/' . $path . '.bb') === '' &&
load_doc_file('doc/' . $path . '.html') === ''
load_doc_file($fullpath . '.md') === '' &&
load_doc_file($fullpath . '.bb') === '' &&
load_doc_file($fullpath . '.html') === ''
) {
$path = $title;
}
$text = load_doc_file('doc/' . $path . '.md');
$fullpath = get_help_fullpath($path);
$text = load_doc_file($fullpath . '.md');
if(! $text) {
$text = load_doc_file('doc/' . $path . '.bb');
$text = load_doc_file($fullpath . '.bb');
if($text)
$doctype = 'bbcode';
}
if(! $text) {
$text = load_doc_file('doc/' . $path . '.html');
$text = load_doc_file($fullpath . '.html');
if($text)
$doctype = 'html';
}
@ -64,12 +111,16 @@ function get_help_content($tocpath = false) {
if($tocpath === false) {
if(! $text) {
$text = load_doc_file('doc/Site.md');
$path = 'Site';
$fullpath = get_help_fullpath($path,'.md');
$text = load_doc_file($fullpath . '.md');
\App::$page['title'] = t('Help');
}
if(! $text) {
$doctype = 'bbcode';
$text = load_doc_file('doc/main.bb');
$path = 'main';
$fullpath = get_help_fullpath($path,'.md');
$text = load_doc_file($fullpath . '.bb');
goaway('/help/about/about');
\App::$page['title'] = t('Help');
}
@ -146,35 +197,7 @@ function determine_help_language() {
}
function load_doc_file($s) {
$path = 'doc';
// Determine the language and modify the path accordingly
$x = determine_help_language();
$lang = $x['language'];
$url_idx = ($x['from_url'] ? 1 : 0);
// The English translation is at the root of /doc/. Other languages are in
// subfolders named by the language code such as "de", "es", etc.
if($lang !== 'en') {
$path .= '/' . $lang;
}
$b = basename($s);
for($i=1+$url_idx; $i<argc()-1; $i++) {
$path .= '/' . argv($i);
}
$c = find_doc_file($path . '/' . $b);
if($c)
return $c;
// Possibly a translation was requested that has not been translated, so fall
// back to the English version
$path = 'doc';
for($i=1+$url_idx; $i<argc()-1; $i++) {
$path .= '/' . argv($i);
}
$c = find_doc_file($path . '/' . $b);
if($c)
return $c;
// Try one last time to find the file at the explicit path input to the function
$c = find_doc_file($s);
if($c)
return $c;

View file

@ -228,25 +228,31 @@ function can_comment_on_post($observer_xchan, $item) {
call_hooks('can_comment_on_post', $x);
if($x['allowed'] !== 'unset')
if($x['allowed'] !== 'unset') {
return $x['allowed'];
}
if(! $observer_xchan)
if(! $observer_xchan) {
return false;
}
if($item['comment_policy'] === 'none')
if($item['comment_policy'] === 'none') {
return false;
}
if(comments_are_now_closed($item))
if(comments_are_now_closed($item)) {
return false;
}
if($observer_xchan === $item['author_xchan'] || $observer_xchan === $item['owner_xchan'])
if($observer_xchan === $item['author_xchan'] || $observer_xchan === $item['owner_xchan']) {
return true;
}
switch($item['comment_policy']) {
case 'self':
if($observer_xchan === $item['author_xchan'] || $observer_xchan === $item['owner_xchan'])
if($observer_xchan === $item['author_xchan'] || $observer_xchan === $item['owner_xchan']) {
return true;
}
break;
case 'public':
case 'authenticated':
@ -258,17 +264,23 @@ function can_comment_on_post($observer_xchan, $item) {
case 'any connections':
case 'contacts':
case '':
if(local_channel() && array_key_exists('owner',$item) && their_perms_contains(local_channel(),$item['owner']['abook_xchan'],'post_comments')) {
return true;
}
if(intval($item['item_wall']) && perm_is_allowed($item['uid'],$observer_xchan,'post_comments')) {
return true;
}
break;
default:
break;
}
if(strstr($item['comment_policy'],'network:') && strstr($item['comment_policy'],'red'))
if(strstr($item['comment_policy'],'network:') && strstr($item['comment_policy'],'red')) {
return true;
if(strstr($item['comment_policy'],'site:') && strstr($item['comment_policy'],App::get_hostname()))
}
if(strstr($item['comment_policy'],'site:') && strstr($item['comment_policy'],App::get_hostname())) {
return true;
}
return false;
}

View file

@ -82,10 +82,10 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) {
$s = preg_replace_callback("/\[img\](.*?)\[\/img\]/ism", 'use_zrl_cb_img', $s);
$s = preg_replace_callback("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", 'use_zrl_cb_img_x', $s);
}
$s = preg_replace_callback("/([^\]\=\{]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", 'use_zrl_cb_link',$s);
$s = preg_replace_callback("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", 'use_zrl_cb_link',$s);
}
else {
$s = preg_replace("/([^\]\=\{]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[url=$2$3]$2$3[/url]',$s);
$s = preg_replace("/([^\]\=\{\/]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[url=$2$3]$2$3[/url]',$s);
}
// remove duplicate adjacent code tags

View file

@ -959,9 +959,8 @@ function format_js_if_exists($source) {
function theme_include($file, $root = '') {
// Make sure $root ends with a slash / if it's not blank
if($root !== '' && $root[strlen($root)-1] !== '/')
if($root !== '' && substr($root,-1) !== '/')
$root = $root . '/';
$theme_info = App::$theme_info;
if(array_key_exists('extends',$theme_info))
@ -992,21 +991,51 @@ function theme_include($file, $root = '') {
return '';
}
function get_intltext_template($s, $root = '') {
$testroot = ($root=='') ? $testroot = "ROOT" : $root;
$t = App::template_engine();
$t = App::template_engine();
$template = $t->get_intltext_template($s, $root);
return $template;
if (isset(\App::$override_intltext_templates[$testroot][$s]["content"])) {
return \App::$override_intltext_templates[$testroot][$s]["content"];
} else {
if (isset(\App::$override_intltext_templates[$testroot][$s]["root"]) &&
isset(\App::$override_intltext_templates[$testroot][$s]["file"])) {
$s = \App::$override_intltext_templates[$testroot][$s]["file"];
$root = \App::$override_intltext_templates[$testroot][$s]["root"];
} elseif (\App::$override_templateroot) {
$newroot = \App::$override_templateroot.$root;
if ($newroot != '' && substr($newroot,-1) != '/' ) {
$newroot .= '/';
}
$template = $t->get_intltext_template($s, $newroot);
}
$template = $t->get_intltext_template($s, $root);
return $template;
}
}
function get_markup_template($s, $root = '') {
$testroot = ($root=='') ? $testroot = "ROOT" : $root;
$t = App::template_engine();
$template = $t->get_markup_template($s, $root);
return $template;
$t = App::template_engine();
if (isset(\App::$override_markup_templates[$testroot][$s]["content"])) {
return \App::$override_markup_templates[$testroot][$s]["content"];
} else {
if (isset(\App::$override_markup_templates[$testroot][$s]["root"]) &&
isset(\App::$override_markup_templates[$testroot][$s]["file"])) {
$s = \App::$override_markup_templates[$testroot][$s]["file"];
$root = \App::$override_markup_templates[$testroot][$s]["root"];
} elseif (\App::$override_templateroot) {
$newroot = \App::$override_templateroot.$root;
if ($newroot != '' && substr($newroot,-1) != '/' ) {
$newroot .= '/';
}
$template = $t->get_markup_template($s, $newroot);
}
$template = $t->get_markup_template($s, $root);
return $template;
}
}
/**

View file

@ -2055,6 +2055,7 @@ function undo_post_tagging($s) {
$cnt = preg_match_all('/([@#])(\!*)\[zrl=(.*?)\](.*?)\[\/zrl\]/ism',$s,$matches,PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
$x = false;
if($mtch[1] === '@') {
$x = q("select xchan_addr, xchan_url from xchan where xchan_url = '%s' limit 1",
dbesc($mtch[3])
@ -3266,17 +3267,17 @@ function cleanup_bbcode($body) {
* First protect any url inside certain bbcode tags so we don't double link it.
*/
$body = preg_replace_callback('/\[code(.*?)\[\/(code)\]/ism','\red_escape_codeblock',$body);
$body = preg_replace_callback('/\[url(.*?)\[\/(url)\]/ism','\red_escape_codeblock',$body);
$body = preg_replace_callback('/\[zrl(.*?)\[\/(zrl)\]/ism','\red_escape_codeblock',$body);
$body = preg_replace_callback("/([^\]\='".'"'."\/\{]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\
+\,\(\)]+)/ismu", '\nakedoembed', $body);
$body = preg_replace_callback("/([^\]\='".'"'."\/\{]|^|\#\^)(https?\:\/\/[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\\
+\,\(\)]+)/ismu", '\red_zrl_callback', $body);
$body = preg_replace_callback('/\[\$b64zrl(.*?)\[\/(zrl)\]/ism','\red_unescape_codeblock',$body);
$body = preg_replace_callback('/\[\$b64url(.*?)\[\/(url)\]/ism','\red_unescape_codeblock',$body);
$body = preg_replace_callback('/\[\$b64code(.*?)\[\/(code)\]/ism','\red_unescape_codeblock',$body);

View file

@ -503,6 +503,7 @@ CREATE TABLE IF NOT EXISTS `hook` (
KEY `hook_version` (`hook_version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `hubloc` (
`hubloc_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`hubloc_guid` char(191) NOT NULL DEFAULT '',
@ -546,7 +547,6 @@ CREATE TABLE IF NOT EXISTS `hubloc` (
KEY `hubloc_error` (`hubloc_error`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `iconfig` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`iid` int(11) NOT NULL DEFAULT 0 ,

View file

@ -476,6 +476,7 @@ create index "hook_idx" on hook ("hook");
create index "hook_version_idx" on hook ("hook_version");
create index "hook_priority_idx" on hook ("priority");
CREATE TABLE "hubloc" (
"hubloc_id" serial NOT NULL,
"hubloc_guid" text NOT NULL DEFAULT '',