Merge branch '3.8RC'

This commit is contained in:
Mario Vavti
2018-10-19 11:18:28 +02:00
862 changed files with 98136 additions and 29195 deletions

View File

@@ -124,7 +124,7 @@ function account_store_lowlevel($arr) {
'account_expires' => ((array_key_exists('account_expires',$arr)) ? $arr['account_expires'] : '0001-01-01 00:00:00'),
'account_expire_notified' => ((array_key_exists('account_expire_notified',$arr)) ? $arr['account_expire_notified'] : '0001-01-01 00:00:00'),
'account_service_class' => ((array_key_exists('account_service_class',$arr)) ? $arr['account_service_class'] : ''),
'account_level' => ((array_key_exists('account_level',$arr)) ? $arr['account_level'] : '0'),
'account_level' => '5',
'account_password_changed' => ((array_key_exists('account_password_changed',$arr)) ? $arr['account_password_changed'] : '0001-01-01 00:00:00')
];
@@ -215,7 +215,7 @@ function create_account($arr) {
'account_created' => datetime_convert(),
'account_flags' => intval($flags),
'account_roles' => intval($roles),
'account_level' => intval($techlevel),
'account_level' => 5,
'account_expires' => $expires,
'account_service_class' => $default_service_class
]
@@ -821,13 +821,6 @@ function upgrade_bool_message($bbcode = false) {
function get_account_techlevel($account_id = 0) {
if(! $account_id) {
$x = \App::get_account();
}
else {
$x = get_account_by_id($account_id);
}
return (($x) ? intval($x['account_level']) : 0);
return (5);
}

View File

@@ -89,7 +89,7 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
}
}
$r = q("SELECT id, hash, gname FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
$r = q("SELECT id, hash, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval(local_channel())
);

View File

@@ -127,7 +127,10 @@ require_once('include/api_zot.php');
}
}
$x = [ 'path' => App::$query_string ];
call_hooks('api_not_found',$x);
header('HTTP/1.1 404 Not Found');
logger('API call not implemented: ' . App::$query_string . ' - ' . print_r($_REQUEST,true));

View File

@@ -12,7 +12,13 @@ function api_login(&$a){
require_once('include/oauth.php');
if(array_key_exists('REDIRECT_REMOTE_USER',$_SERVER) && (! array_key_exists('HTTP_AUTHORIZATION',$_SERVER))) {
$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['REDIRECT_REMOTE_USER'];
}
// login with oauth
try {
// OAuth 2.0
$storage = new \Zotlabs\Identity\OAuth2Storage(\DBA::$dba->db);
@@ -66,32 +72,27 @@ function api_login(&$a){
logger($e->getMessage());
}
// workarounds for HTTP-auth in CGI mode
foreach([ 'REDIRECT_REMOTE_USER', 'HTTP_AUTHORIZATION' ] as $head) {
if(array_key_exists('HTTP_AUTHORIZATION',$_SERVER)) {
/* Basic authentication */
if(array_key_exists($head,$_SERVER) && substr(trim($_SERVER[$head]),0,5) === 'Basic') {
$userpass = @base64_decode(substr(trim($_SERVER[$head]),6)) ;
if (substr(trim($_SERVER['HTTP_AUTHORIZATION']),0,5) === 'Basic') {
$userpass = @base64_decode(substr(trim($_SERVER['HTTP_AUTHORIZATION']),6)) ;
if(strlen($userpass)) {
list($name, $password) = explode(':', $userpass);
$_SERVER['PHP_AUTH_USER'] = $name;
$_SERVER['PHP_AUTH_PW'] = $password;
}
break;
}
/* Signature authentication */
/* OpenWebAuth */
if(array_key_exists($head,$_SERVER) && substr(trim($_SERVER[$head]),0,9) === 'Signature') {
if(substr(trim($_SERVER['HTTP_AUTHORIZATION']),0,9) === 'Signature') {
if($head !== 'HTTP_AUTHORIZATION') {
$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER[$head];
continue;
}
$record = null;
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER['HTTP_AUTHORIZATION']);
if($sigblock) {
$keyId = str_replace('acct:','',$sigblock['keyId']);
if($keyId) {
@@ -108,16 +109,7 @@ function api_login(&$a){
$record = [ 'channel' => $c, 'account' => $a[0] ];
$channel_login = $c['channel_id'];
}
else {
continue;
}
}
else {
continue;
}
}
else {
continue;
}
if($record) {
@@ -125,7 +117,6 @@ function api_login(&$a){
if(! ($verified && $verified['header_signed'] && $verified['header_valid'])) {
$record = null;
}
break;
}
}
}
@@ -137,7 +128,7 @@ function api_login(&$a){
// process normal login request
if(isset($_SERVER['PHP_AUTH_USER'])) {
if(isset($_SERVER['PHP_AUTH_USER']) && (! $record)) {
$channel_login = 0;
$record = account_verify_password($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']);
if($record && $record['channel']) {

View File

@@ -350,20 +350,20 @@
$r = null;
if($_REQUEST['group_id']) {
$r = q("select * from groups where uid = %d and id = %d limit 1",
$r = q("select * from pgrp where uid = %d and id = %d limit 1",
intval(api_user()),
intval($_REQUEST['group_id'])
);
}
elseif($_REQUEST['group_name']) {
$r = q("select * from groups where uid = %d and gname = '%s' limit 1",
$r = q("select * from pgrp where uid = %d and gname = '%s' limit 1",
intval(api_user()),
dbesc($_REQUEST['group_name'])
);
}
if($r) {
$x = q("select * from group_member left join abook on abook_xchan = xchan and abook_channel = group_member.uid left join xchan on group_member.xchan = xchan.xchan_hash
$x = q("select * from pgrp_member left join abook on abook_xchan = xchan and abook_channel = pgrp_member.uid left join xchan on pgrp_member.xchan = xchan.xchan_hash
where gid = %d",
intval($r[0]['id'])
);
@@ -376,7 +376,7 @@
if(api_user() === false)
return false;
$r = q("select * from groups where uid = %d",
$r = q("select * from pgrp where uid = %d",
intval(api_user())
);
json_return_and_die($r);

View File

@@ -1428,6 +1428,8 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
if(! $r) {
attach_drop_photo($channel_id,$resource);
$arr = ['channel_id' => $channel_id, 'resource' => $resource, 'is_photo'=>$is_photo];
call_hooks("attach_delete",$arr);
return;
}
@@ -1486,6 +1488,9 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
intval($channel_id)
);
$arr = ['channel_id' => $channel_id, 'resource' => $resource, 'is_photo'=>$is_photo];
call_hooks("attach_delete",$arr);
file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', true);
return;

View File

@@ -953,12 +953,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);
@@ -966,9 +968,6 @@ function bbcode($Text, $options = []) {
$Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>', $Text);
}
if (get_account_techlevel() < 2)
$Text = str_replace('<span class="bookmark-identifier">#^</span>', '', $Text);
// Perform MAIL Search
if (strpos($Text,'[/mail]') !== false) {
$Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1" ' . $target . ' rel="nofollow noopener" >$1</a>', $Text);

View File

@@ -59,9 +59,10 @@ function bookmark_add($channel,$sender,$taxonomy,$private,$opts = null) {
);
if($r)
logger('add_bookmark: duplicate menu entry', LOGGER_DEBUG);
if(! $r)
if(! $r) {
$r = menu_add_item($menu_id,$channel_id,$iarr);
menu_sync_packet($channel_id,get_observer_hash(),$menu_id);
}
return $r;
}

View File

@@ -4,6 +4,13 @@
* @brief Channel related functions.
*/
use Zotlabs\Access\PermissionRoles;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Access\Permissions;
use Zotlabs\Daemon\Master;
use Zotlabs\Lib\System;
use Zotlabs\Render\Comanche;
require_once('include/zot.php');
require_once('include/crypto.php');
require_once('include/menu.php');
@@ -236,7 +243,7 @@ function create_identity($arr) {
$role_permissions = null;
if(array_key_exists('permissions_role',$arr) && $arr['permissions_role']) {
$role_permissions = \Zotlabs\Access\PermissionRoles::role_perms($arr['permissions_role']);
$role_permissions = PermissionRoles::role_perms($arr['permissions_role']);
}
if($role_permissions && array_key_exists('directory_publish',$role_permissions))
@@ -307,7 +314,7 @@ function create_identity($arr) {
$perm_limits = site_default_perms();
foreach($perm_limits as $p => $v)
\Zotlabs\Access\PermissionLimits::Set($r[0]['channel_id'],$p,$v);
PermissionLimits::Set($r[0]['channel_id'],$p,$v);
if($role_permissions && array_key_exists('perms_auto',$role_permissions))
set_pconfig($r[0]['channel_id'],'system','autoperms',intval($role_permissions['perms_auto']));
@@ -383,7 +390,7 @@ function create_identity($arr) {
$myperms = ((array_key_exists('perms_connect',$role_permissions)) ? $role_permissions['perms_connect'] : array());
}
else {
$x = \Zotlabs\Access\PermissionRoles::role_perms('social');
$x = PermissionRoles::role_perms('social');
$myperms = $x['perms_connect'];
}
@@ -399,7 +406,7 @@ function create_identity($arr) {
]
);
$x = \Zotlabs\Access\Permissions::FilledPerms($myperms);
$x = Permissions::FilledPerms($myperms);
foreach($x as $k => $v) {
set_abconfig($newuid,$hash,'my_perms',$k,$v);
}
@@ -416,7 +423,7 @@ function create_identity($arr) {
$autoperms = intval($role_permissions['perms_auto']);
set_pconfig($newuid,'system','autoperms',$autoperms);
if($autoperms) {
$x = \Zotlabs\Access\Permissions::FilledPerms($role_permissions['perms_connect']);
$x = Permissions::FilledPerms($role_permissions['perms_connect']);
foreach($x as $k => $v) {
set_pconfig($newuid,'autoperms',$k,$v);
}
@@ -440,7 +447,7 @@ function create_identity($arr) {
// if our role_permissions indicate that we're using a default collection ACL, add it.
if(is_array($role_permissions) && $role_permissions['default_collection']) {
$r = q("select hash from groups where uid = %d and gname = '%s' limit 1",
$r = q("select hash from pgrp where uid = %d and gname = '%s' limit 1",
intval($newuid),
dbesc( t('Friends') )
);
@@ -482,7 +489,7 @@ function create_identity($arr) {
*/
call_hooks('create_identity', $newuid);
Zotlabs\Daemon\Master::Summon(array('Directory', $ret['channel']['channel_id']));
Master::Summon(array('Directory', $ret['channel']['channel_id']));
}
$ret['success'] = true;
@@ -583,7 +590,7 @@ function change_channel_keys($channel) {
xchan_change_key($oldxchan,$newxchan,$stored);
Zotlabs\Daemon\Master::Summon(array('Notifier', 'keychange', $channel['channel_id']));
Master::Summon([ 'Notifier', 'keychange', $channel['channel_id'] ]);
$ret['success'] = true;
return $ret;
@@ -666,7 +673,7 @@ function channel_change_address($channel,$new_address) {
}
}
Zotlabs\Daemon\Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
$ret['success'] = true;
return $ret;
@@ -759,7 +766,7 @@ function identity_basic_export($channel_id, $sections = null) {
'project' => PLATFORM_NAME,
'version' => STD_VERSION,
'database' => DB_UPDATE_VERSION,
'server_role' => Zotlabs\Lib\System::get_server_role()
'server_role' => System::get_server_role()
];
/*
@@ -830,14 +837,14 @@ function identity_basic_export($channel_id, $sections = null) {
$ret['hubloc'] = $r;
}
$r = q("select * from groups where uid = %d ",
$r = q("select * from pgrp where uid = %d ",
intval($channel_id)
);
if($r)
$ret['group'] = $r;
$r = q("select * from group_member where uid = %d ",
$r = q("select * from pgrp_member where uid = %d ",
intval($channel_id)
);
if($r)
@@ -1425,7 +1432,7 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
}
$menublock = get_pconfig($profile['uid'],'system','channel_menublock');
if ($menublock && (! $block)) {
$comanche = new Zotlabs\Render\Comanche();
$comanche = new Comanche();
$channel_menu .= $comanche->block($menublock);
}
@@ -1701,7 +1708,7 @@ function zid_init() {
dbesc($tmp_str)
);
if(! $r) {
Zotlabs\Daemon\Master::Summon(array('Gprobe',bin2hex($tmp_str)));
Master::Summon(array('Gprobe',bin2hex($tmp_str)));
}
if($r && remote_channel() && remote_channel() === $r[0]['hubloc_hash'])
return;
@@ -1907,7 +1914,7 @@ function is_public_profile() {
$channel = App::get_channel();
if($channel) {
$perm = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_profile');
$perm = PermissionLimits::Get($channel['channel_id'],'view_profile');
if($perm == PERMS_PUBLIC)
return true;
}
@@ -2526,6 +2533,12 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
if(! $local) {
if(intval($r[0]['channel_removed'])) {
// already removed. do not propagate deletion of a channel which
// may have been removed locally at some previous time.
return;
}
$r = q("update channel set channel_deleted = '%s', channel_removed = 1 where channel_id = %d",
dbesc(datetime_convert()),
intval($channel_id)
@@ -2545,11 +2558,11 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
dbesc($channel['channel_hash'])
);
Zotlabs\Daemon\Master::Summon(array('Notifier','purge_all',$channel_id));
Master::Summon(array('Notifier','purge_all',$channel_id));
}
$r = q("select * from iconfig left join item on item.id = iconfig.iid
$r = q("select iid from iconfig left join item on item.id = iconfig.iid
where item.uid = %d",
intval($channel_id)
);
@@ -2566,8 +2579,8 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
q("DELETE FROM chatroom WHERE cr_uid = %d", intval($channel_id));
q("DELETE FROM conv WHERE uid = %d", intval($channel_id));
q("DELETE FROM groups WHERE uid = %d", intval($channel_id));
q("DELETE FROM group_member WHERE uid = %d", intval($channel_id));
q("DELETE FROM pgrp WHERE uid = %d", intval($channel_id));
q("DELETE FROM pgrp_member WHERE uid = %d", intval($channel_id));
q("DELETE FROM event WHERE uid = %d", intval($channel_id));
q("DELETE FROM mail WHERE channel_id = %d", intval($channel_id));
q("DELETE FROM menu WHERE menu_channel_id = %d", intval($channel_id));
@@ -2589,8 +2602,6 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
}
}
$r = q("select id from item where uid = %d", intval($channel_id));
if($r) {
foreach($r as $rv) {
@@ -2598,7 +2609,6 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
}
}
q("delete from abook where abook_xchan = '%s' and abook_self = 1 ",
dbesc($channel['channel_hash'])
);
@@ -2658,7 +2668,7 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
@rrmdir($f);
}
Zotlabs\Daemon\Master::Summon(array('Directory',$channel_id));
Master::Summon([ 'Directory', $channel_id ]);
if($channel_id == local_channel() && $unset_session) {
App::$session->nuke();
@@ -2797,3 +2807,6 @@ function pchan_to_chan($pchan) {
return $chan;
}
function channel_url($channel) {
return (($channel) ? z_root() . '/channel/' . $channel['channel_address'] : z_root());
}

View File

@@ -296,7 +296,7 @@ function remove_all_xchan_resources($xchan, $channel_id = 0) {
$r = q("delete from event where event_xchan = '%s'",
dbesc($xchan)
);
$r = q("delete from group_member where xchan = '%s'",
$r = q("delete from pgrp_member where xchan = '%s'",
dbesc($xchan)
);
$r = q("delete from mail where ( from_xchan = '%s' or to_xchan = '%s' )",
@@ -404,7 +404,7 @@ function contact_remove($channel_id, $abook_id) {
intval($channel_id)
);
$r = q("delete from group_member where xchan = '%s' and uid = %d",
$r = q("delete from pgrp_member where xchan = '%s' and uid = %d",
dbesc($abook['abook_xchan']),
intval($channel_id)
);

View File

@@ -888,6 +888,7 @@ function conversation($items, $mode, $update, $page_mode = 'traditional', $prepa
'$user' => App::$user,
'$threads' => $threads,
'$wait' => t('Loading...'),
'$conversation_tools' => t('Conversation Tools'),
'$dropping' => ($page_dropping?t('Delete Selected Items'):False),
));
@@ -1231,13 +1232,27 @@ function format_like($cnt, $arr, $type, $id) {
return $o;
}
/**
* Wrapper to allow addons to replace the status editor if desired.
*/
function status_editor($a, $x, $popup = false, $module='') {
$hook_info = ['editor_html' => '', 'x' => $x, 'popup' => $popup, 'module' => $module];
call_hooks('status_editor',$hook_info);
if ($hook_info['editor_html'] == '') {
return hz_status_editor($a, $x, $popup);
} else {
return $hook_info['editor_html'];
}
}
/**
* This is our general purpose content editor.
* It was once nicknamed "jot" and you may see references to "jot" littered throughout the code.
* They are referring to the content editor or components thereof.
*/
function status_editor($a, $x, $popup = false) {
function hz_status_editor($a, $x, $popup = false) {
$o = '';
@@ -1447,7 +1462,8 @@ function status_editor($a, $x, $popup = false) {
'$expanded' => ((x($x, 'expanded')) ? $x['expanded'] : false),
'$bbcode' => ((x($x, 'bbcode')) ? $x['bbcode'] : false),
'$parent' => ((array_key_exists('parent',$x) && $x['parent']) ? $x['parent'] : 0),
'$reset' => $reset
'$reset' => $reset,
'$is_owner' => ((local_channel() && (local_channel() == $x['profile_uid'])) ? true : false)
));
if ($popup === true) {
@@ -1644,319 +1660,6 @@ function prepare_page($item) {
));
}
function network_tabs() {
$no_active='';
$starred_active = '';
$new_active = '';
$all_active = '';
$search_active = '';
$conv_active = '';
$spam_active = '';
$postord_active = '';
if(x($_GET,'new')) {
$new_active = 'active';
}
if(x($_GET,'search')) {
$search_active = 'active';
}
if(x($_GET,'star')) {
$starred_active = 'active';
}
if(x($_GET,'conv')) {
$conv_active = 'active';
}
if(x($_GET,'spam')) {
$spam_active = 'active';
}
if (($new_active == '')
&& ($starred_active == '')
&& ($conv_active == '')
&& ($search_active == '')
&& ($spam_active == '')) {
$no_active = 'active';
}
if ($no_active=='active' && x($_GET,'order')) {
switch($_GET['order']){
case 'post': $postord_active = 'active'; $no_active=''; break;
case 'comment' : $all_active = 'active'; $no_active=''; break;
}
}
if ($no_active=='active') $all_active='active';
$cmd = App::$cmd;
// tabs
$tabs = array();
$tabs[] = array(
'label' => t('Commented Order'),
'url'=>z_root() . '/' . $cmd . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
'sel'=>$all_active,
'title'=> t('Sort by Comment Date'),
);
$tabs[] = array(
'label' => t('Posted Order'),
'url'=>z_root() . '/' . $cmd . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
'sel'=>$postord_active,
'title' => t('Sort by Post Date'),
);
if(feature_enabled(local_channel(),'personal_tab')) {
$tabs[] = array(
'label' => t('Personal'),
'url' => z_root() . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&conv=1',
'sel' => $conv_active,
'title' => t('Posts that mention or involve you'),
);
}
if(feature_enabled(local_channel(),'new_tab')) {
$tabs[] = array(
'label' => t('New'),
'url' => z_root() . '/' . $cmd . '?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&new=1' . ((x($_GET,'gid')) ? '&gid=' . $_GET['gid'] : ''),
'sel' => $new_active,
'title' => t('Activity Stream - by date'),
);
}
if(feature_enabled(local_channel(),'star_posts')) {
$tabs[] = array(
'label' => t('Starred'),
'url'=>z_root() . '/' . $cmd . '/?f=' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : '') . '&star=1',
'sel'=>$starred_active,
'title' => t('Favourite Posts'),
);
}
// Not yet implemented
if(feature_enabled(local_channel(),'spam_filter')) {
$tabs[] = array(
'label' => t('Spam'),
'url'=> z_root() . '/network?f=&spam=1',
'sel'=> $spam_active,
'title' => t('Posts flagged as SPAM'),
);
}
$arr = array('tabs' => $tabs);
call_hooks('network_tabs', $arr);
$tpl = get_markup_template('common_tabs.tpl');
return replace_macros($tpl, array('$tabs' => $arr['tabs']));
}
/**
* @brief
*
* @param App $a
* @param boolean $is_owner default false
* @param string $nickname default null
* @return void|string
*/
function profile_tabs($a, $is_owner = false, $nickname = null){
// Don't provide any profile tabs if we're running as the sys channel
if (App::$is_sys)
return;
if (get_pconfig($uid, 'system', 'noprofiletabs'))
return;
$channel = App::get_channel();
if (is_null($nickname))
$nickname = $channel['channel_address'];
$uid = ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : local_channel());
$account_id = ((App::$profile['profile_uid']) ? App::$profile['channel_account_id'] : App::$channel['channel_account_id']);
if ($uid == local_channel())
return;
if($uid == local_channel()) {
$cal_link = '';
}
else {
$cal_link = '/cal/' . $nickname;
}
require_once('include/security.php');
$sql_options = item_permissions_sql($uid);
$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 item.item_delayed = 0 and item.item_deleted = 0
and ( iconfig.k = 'WEBPAGE' and item_type = %d )
$sql_options limit 1",
intval($uid),
dbesc('home'),
intval(ITEM_TYPE_WEBPAGE)
);
$has_webpages = (($r) ? true : false);
if (x($_GET, 'tab'))
$tab = notags(trim($_GET['tab']));
$url = z_root() . '/channel/' . $nickname;
$pr = z_root() . '/profile/' . $nickname;
$tabs = array(
array(
'label' => t('Channel'),
'url' => $url,
'sel' => ((argv(0) == 'channel') ? 'active' : ''),
'title' => t('Status Messages and Posts'),
'id' => 'status-tab',
'icon' => 'home'
),
);
$p = get_all_perms($uid,get_observer_hash());
if ($p['view_profile']) {
$tabs[] = array(
'label' => t('About'),
'url' => $pr,
'sel' => ((argv(0) == 'profile') ? 'active' : ''),
'title' => t('Profile Details'),
'id' => 'profile-tab',
'icon' => 'user'
);
}
if ($p['view_storage']) {
$tabs[] = array(
'label' => t('Photos'),
'url' => z_root() . '/photos/' . $nickname,
'sel' => ((argv(0) == 'photos') ? 'active' : ''),
'title' => t('Photo Albums'),
'id' => 'photo-tab',
'icon' => 'photo'
);
$tabs[] = array(
'label' => t('Files'),
'url' => z_root() . '/cloud/' . $nickname,
'sel' => ((argv(0) == 'cloud' || argv(0) == 'sharedwithme') ? 'active' : ''),
'title' => t('Files and Storage'),
'id' => 'files-tab',
'icon' => 'folder-open'
);
}
if($p['view_stream'] && $cal_link) {
$tabs[] = array(
'label' => t('Events'),
'url' => z_root() . $cal_link,
'sel' => ((argv(0) == 'cal' || argv(0) == 'events') ? 'active' : ''),
'title' => t('Events'),
'id' => 'event-tab',
'icon' => 'calendar'
);
}
if ($p['chat'] && feature_enabled($uid,'ajaxchat')) {
$has_chats = Zotlabs\Lib\Chatroom::list_count($uid);
if ($has_chats) {
$tabs[] = array(
'label' => t('Chatrooms'),
'url' => z_root() . '/chat/' . $nickname,
'sel' => ((argv(0) == 'chat') ? 'active' : '' ),
'title' => t('Chatrooms'),
'id' => 'chat-tab',
'icon' => 'comments-o'
);
}
}
require_once('include/menu.php');
$has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
if($is_owner && $has_bookmarks) {
$tabs[] = array(
'label' => t('Bookmarks'),
'url' => z_root() . '/bookmarks',
'sel' => ((argv(0) == 'bookmarks') ? 'active' : ''),
'title' => t('Saved Bookmarks'),
'id' => 'bookmarks-tab',
'icon' => 'bookmark'
);
}
if(feature_enabled($uid,'cards')) {
$tabs[] = array(
'label' => t('Cards'),
'url' => z_root() . '/cards/' . $nickname,
'sel' => ((argv(0) == 'cards') ? 'active' : ''),
'title' => t('View Cards'),
'id' => 'cards-tab',
'icon' => 'list'
);
}
if(feature_enabled($uid,'articles')) {
$tabs[] = array(
'label' => t('articles'),
'url' => z_root() . '/articles/' . $nickname,
'sel' => ((argv(0) == 'articles') ? 'active' : ''),
'title' => t('View Articles'),
'id' => 'articles-tab',
'icon' => 'file-text-o'
);
}
if($has_webpages && feature_enabled($uid,'webpages')) {
$tabs[] = array(
'label' => t('Webpages'),
'url' => z_root() . '/page/' . $nickname . '/home',
'sel' => ((argv(0) == 'webpages') ? 'active' : ''),
'title' => t('View Webpages'),
'id' => 'webpages-tab',
'icon' => 'newspaper-o'
);
}
if ($p['view_wiki']) {
if(feature_enabled($uid,'wiki') && (get_account_techlevel($account_id) > 3)) {
$tabs[] = array(
'label' => t('Wikis'),
'url' => z_root() . '/wiki/' . $nickname,
'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
'title' => t('Wiki'),
'id' => 'wiki-tab',
'icon' => 'pencil-square-o'
);
}
}
$arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => (($tab) ? $tab : false), 'tabs' => $tabs);
call_hooks('profile_tabs', $arr);
$tpl = get_markup_template('profile_tabs.tpl');
return replace_macros($tpl, array(
'$tabs' => $arr['tabs'],
'$name' => App::$profile['channel_name'],
'$thumb' => App::$profile['thumb']
));
}
function get_responses($conv_responses,$response_verbs,$ob,$item) {
$ret = array();

View File

@@ -44,417 +44,98 @@ function feature_level($feature,$def) {
return $def;
}
function process_module_features_get($uid, $features) {
unset($features[0]);
foreach($features as $f) {
$arr[] = [
'feature_' . $f[0],
$f[1],
((intval(feature_enabled($uid, $f[0]))) ? "1" : ''),
$f[2],
[t('Off'),t('On')],
(($f[4] === false) ? '' : 'disabled'),
$f[5]
];
}
return $arr;
}
function process_module_features_post($uid, $features, $post_arr) {
unset($features[0]);
foreach($features as $f) {
$k = $f[0];
if(array_key_exists("feature_$k",$post_arr))
set_pconfig($uid,'feature',$k, (string) $post_arr["feature_$k"]);
else
set_pconfig($uid,'feature', $k, '');
}
}
function get_features($filtered = true, $level = (-1)) {
$account = \App::get_account();
$arr = [
// General
'general' => [
'calendar' => [
t('General Features'),
t('CalDAV'),
[
'start_menu',
t('New Member Links'),
t('Display new member quick links menu'),
(($account['account_created'] > datetime_convert('','','now - 60 days')) ? true : false),
get_config('feature_lock','start_menu'),
feature_level('start_menu',1),
],
[
'advanced_profiles',
t('Advanced Profiles'),
t('Additional profile sections and selections'),
'cal_first_day',
t('Start calendar week on Monday'),
t('Default is Sunday'),
false,
get_config('feature_lock','advanced_profiles'),
feature_level('advanced_profiles',1),
],
[
'profile_export',
t('Profile Import/Export'),
t('Save and load profile details across sites/channels'),
false,
get_config('feature_lock','profile_export'),
feature_level('profile_export',3),
],
[
'webpages',
t('Web Pages'),
t('Provide managed web pages on your channel'),
false,
get_config('feature_lock','webpages'),
feature_level('webpages',3),
],
[
'wiki',
t('Wiki'),
t('Provide a wiki for your channel'),
false,
get_config('feature_lock','wiki'),
feature_level('wiki',2),
],
/*
[
'hide_rating',
t('Hide Rating'),
t('Hide the rating buttons on your channel and profile pages. Note: People can still rate you somewhere else.'),
false,
get_config('feature_lock','hide_rating'),
feature_level('hide_rating',3),
],
*/
[
'private_notes',
t('Private Notes'),
t('Enables a tool to store notes and reminders (note: not encrypted)'),
false,
get_config('feature_lock','private_notes'),
feature_level('private_notes',1),
],
[
'cards',
t('Cards'),
t('Create personal planning cards'),
false,
get_config('feature_lock','cards'),
feature_level('cards',1),
],
[
'articles',
t('Articles'),
t('Create interactive articles'),
false,
get_config('feature_lock','articles'),
feature_level('articles',1),
],
[
'nav_channel_select',
t('Navigation Channel Select'),
t('Change channels directly from within the navigation dropdown menu'),
false,
get_config('feature_lock','nav_channel_select'),
feature_level('nav_channel_select',3),
],
[
'photo_location',
t('Photo Location'),
t('If location data is available on uploaded photos, link this to a map.'),
false,
get_config('feature_lock','photo_location'),
feature_level('photo_location',2),
],
[
'ajaxchat',
t('Access Controlled Chatrooms'),
t('Provide chatrooms and chat services with access control.'),
true,
get_config('feature_lock','ajaxchat'),
feature_level('ajaxchat',1),
],
[
'smart_birthdays',
t('Smart Birthdays'),
t('Make birthday events timezone aware in case your friends are scattered across the planet.'),
true,
get_config('feature_lock','smart_birthdays'),
feature_level('smart_birthdays',2),
],
[
'event_tz_select',
t('Event Timezone Selection'),
t('Allow event creation in timezones other than your own.'),
false,
get_config('feature_lock','event_tz_select'),
feature_level('event_tz_select',2),
],
[
'premium_channel',
t('Premium Channel'),
t('Allows you to set restrictions and terms on those that connect with your channel'),
false,
get_config('feature_lock','premium_channel'),
feature_level('premium_channel',4),
],
[
'advanced_dirsearch',
t('Advanced Directory Search'),
t('Allows creation of complex directory search queries'),
false,
get_config('feature_lock','advanced_dirsearch'),
feature_level('advanced_dirsearch',4),
],
[
'advanced_theming',
t('Advanced Theme and Layout Settings'),
t('Allows fine tuning of themes and page layouts'),
false,
get_config('feature_lock','advanced_theming'),
feature_level('advanced_theming',4),
],
],
'access_control' => [
t('Access Control and Permissions'),
[
'groups',
t('Privacy Groups'),
t('Enable management and selection of privacy groups'),
true,
get_config('feature_lock','groups'),
feature_level('groups',0),
],
[
'multi_profiles',
t('Multiple Profiles'),
t('Ability to create multiple profiles'),
false,
get_config('feature_lock','multi_profiles'),
feature_level('multi_profiles',3),
],
[
'permcats',
t('Permission Categories'),
t('Create custom connection permission limits'),
false,
get_config('feature_lock','permcats'),
feature_level('permcats',2),
],
[
'oauth_clients',
t('OAuth1 Clients'),
t('Manage OAuth1 authenticatication tokens for mobile and remote apps.'),
false,
get_config('feature_lock','oauth_clients'),
feature_level('oauth_clients',1),
],
[
'oauth2_clients',
t('OAuth2 Clients'),
t('Manage OAuth2 authenticatication tokens for mobile and remote apps.'),
false,
get_config('feature_lock','oauth2_clients'),
feature_level('oauth2_clients',1),
],
[
'access_tokens',
t('Access Tokens'),
t('Create access tokens so that non-members can access private content.'),
false,
get_config('feature_lock','access_tokens'),
feature_level('access_tokens',2),
],
get_config('feature_lock','cal_first_day')
]
],
// Post composition
'composition' => [
'channel_home' => [
t('Post Composition Features'),
t('Channel Home'),
[
'large_photos',
t('Large Photos'),
t('Include large (1024px) photo thumbnails in posts. If not enabled, use small (640px) photo thumbnails'),
false,
get_config('feature_lock','large_photos'),
feature_level('large_photos',1),
],
[
'channel_sources',
t('Channel Sources'),
t('Automatically import channel content from other channels or feeds'),
false,
get_config('feature_lock','channel_sources'),
feature_level('channel_sources',3),
],
[
'content_encrypt',
t('Even More Encryption'),
t('Allow optional encryption of content end-to-end with a shared secret key'),
false,
get_config('feature_lock','content_encrypt'),
feature_level('content_encrypt',3),
],
[
'consensus_tools',
t('Enable Voting Tools'),
t('Provide a class of post which others can vote on'),
false,
get_config('feature_lock','consensus_tools'),
feature_level('consensus_tools',3),
],
[
'disable_comments',
t('Disable Comments'),
t('Provide the option to disable comments for a post'),
false,
get_config('feature_lock','disable_comments'),
feature_level('disable_comments',2),
],
[
'delayed_posting',
t('Delayed Posting'),
t('Allow posts to be published at a later date'),
false,
get_config('feature_lock','delayed_posting'),
feature_level('delayed_posting',2),
],
[
'content_expire',
t('Content Expiration'),
t('Remove posts/comments and/or private messages at a future time'),
false,
get_config('feature_lock','content_expire'),
feature_level('content_expire',1),
],
[
'suppress_duplicates',
t('Suppress Duplicate Posts/Comments'),
t('Prevent posts with identical content to be published with less than two minutes in between submissions.'),
true,
get_config('feature_lock','suppress_duplicates'),
feature_level('suppress_duplicates',1),
],
[
'auto_save_draft',
t('Auto-save drafts of posts and comments'),
t('Automatically saves post and comment drafts in local browser storage to help prevent accidental loss of compositions'),
true,
get_config('feature_lock','auto_save_draft'),
feature_level('auto_save_draft',1),
],
],
// Network Tools
'net_module' => [
t('Network and Stream Filtering'),
[
'archives',
t('Search by Date'),
'archives',
t('Search by Date'),
t('Ability to select posts by date ranges'),
false,
get_config('feature_lock','archives'),
feature_level('archives',1),
],
[
'savedsearch',
t('Saved Searches'),
t('Save search terms for re-use'),
false,
get_config('feature_lock','savedsearch'),
feature_level('savedsearch',2),
get_config('feature_lock','archives')
],
[
'order_tab',
t('Alternate Stream Order'),
t('Ability to order the stream by last post date, last comment date or unthreaded activities'),
'tagadelic',
t('Tag Cloud'),
t('Provide a personal tag cloud on your channel page'),
false,
get_config('feature_lock','order_tab'),
feature_level('order_tab',2),
get_config('feature_lock','tagadelic'),
],
[
'name_tab',
t('Contact Filter'),
t('Ability to display only posts of a selected contact'),
'channel_list_mode',
t('Use blog/list mode'),
t('Comments will be displayed separately'),
false,
get_config('feature_lock','name_tab'),
feature_level('name_tab',1),
],
get_config('feature_lock','channel_list_mode'),
]
],
[
'forums_tab',
t('Forum Filter'),
t('Ability to display only posts of a specific forum'),
false,
get_config('feature_lock','forums_tab'),
feature_level('forums_tab',1),
],
'connections' => [
[
'personal_tab',
t('Personal Posts Filter'),
t('Ability to display only posts that you\'ve interacted on'),
false,
get_config('feature_lock','personal_tab'),
feature_level('personal_tab',1),
],
[
'affinity',
t('Affinity Tool'),
t('Filter stream activity by depth of relationships'),
false,
get_config('feature_lock','affinity'),
feature_level('affinity',1),
],
[
'suggest',
t('Suggest Channels'),
t('Show friend and connection suggestions'),
false,
get_config('feature_lock','suggest'),
feature_level('suggest',1),
],
t('Connections'),
[
'connfilter',
t('Connection Filtering'),
t('Filter incoming posts from connections based on keywords/content'),
false,
get_config('feature_lock','connfilter'),
feature_level('connfilter',3),
],
get_config('feature_lock','connfilter')
]
],
// Item tools
'tools' => [
'conversation' => [
t('Post/Comment Tools'),
t('Conversation'),
[
'commtag',
@@ -462,16 +143,6 @@ function get_features($filtered = true, $level = (-1)) {
t('Ability to tag existing posts'),
false,
get_config('feature_lock','commtag'),
feature_level('commtag',1),
],
[
'categories',
t('Post Categories'),
t('Add categories to your posts'),
false,
get_config('feature_lock','categories'),
feature_level('categories',1),
],
[
@@ -480,16 +151,6 @@ function get_features($filtered = true, $level = (-1)) {
t('Add emoji reaction ability to posts'),
true,
get_config('feature_lock','emojis'),
feature_level('emojis',1),
],
[
'filing',
t('Saved Folders'),
t('Ability to file posts under folders'),
false,
get_config('feature_lock','filing'),
feature_level('filing',2),
],
[
@@ -498,7 +159,6 @@ function get_features($filtered = true, $level = (-1)) {
t('Ability to dislike posts/comments'),
false,
get_config('feature_lock','dislike'),
feature_level('dislike',1),
],
[
@@ -507,18 +167,270 @@ function get_features($filtered = true, $level = (-1)) {
t('Ability to mark special posts with a star indicator'),
false,
get_config('feature_lock','star_posts'),
feature_level('star_posts',1),
]
],
'directory' => [
t('Directory'),
[
'advanced_dirsearch',
t('Advanced Directory Search'),
t('Allows creation of complex directory search queries'),
false,
get_config('feature_lock','advanced_dirsearch'),
]
],
'editor' => [
t('Editor'),
[
'categories',
t('Post Categories'),
t('Add categories to your posts'),
false,
get_config('feature_lock','categories'),
feature_level('categories',1),
],
[
'tagadelic',
t('Tag Cloud'),
t('Provide a personal tag cloud on your channel page'),
'large_photos',
t('Large Photos'),
t('Include large (1024px) photo thumbnails in posts. If not enabled, use small (640px) photo thumbnails'),
false,
get_config('feature_lock','tagadelic'),
feature_level('tagadelic',2),
get_config('feature_lock','large_photos'),
],
[
'content_encrypt',
t('Even More Encryption'),
t('Allow optional encryption of content end-to-end with a shared secret key'),
false,
get_config('feature_lock','content_encrypt'),
],
[
'consensus_tools',
t('Enable Voting Tools'),
t('Provide a class of post which others can vote on'),
false,
get_config('feature_lock','consensus_tools'),
],
[
'disable_comments',
t('Disable Comments'),
t('Provide the option to disable comments for a post'),
false,
get_config('feature_lock','disable_comments'),
],
[
'delayed_posting',
t('Delayed Posting'),
t('Allow posts to be published at a later date'),
false,
get_config('feature_lock','delayed_posting'),
],
[
'content_expire',
t('Content Expiration'),
t('Remove posts/comments and/or private messages at a future time'),
false,
get_config('feature_lock','content_expire'),
],
[
'suppress_duplicates',
t('Suppress Duplicate Posts/Comments'),
t('Prevent posts with identical content to be published with less than two minutes in between submissions.'),
true,
get_config('feature_lock','suppress_duplicates'),
],
[
'auto_save_draft',
t('Auto-save drafts of posts and comments'),
t('Automatically saves post and comment drafts in local browser storage to help prevent accidental loss of compositions'),
true,
get_config('feature_lock','auto_save_draft'),
]
],
'events' => [
t('Events'),
[
'events_cal_first_day',
t('Start calendar week on Monday'),
t('Default is Sunday'),
false,
get_config('feature_lock','events_cal_first_day')
],
[
'smart_birthdays',
t('Smart Birthdays'),
t('Make birthday events timezone aware in case your friends are scattered across the planet.'),
true,
get_config('feature_lock','smart_birthdays'),
],
[
'event_tz_select',
t('Event Timezone Selection'),
t('Allow event creation in timezones other than your own.'),
false,
get_config('feature_lock','event_tz_select'),
]
],
'manage' => [
t('Manage'),
[
'nav_channel_select',
t('Navigation Channel Select'),
t('Change channels directly from within the navigation dropdown menu'),
false,
get_config('feature_lock','nav_channel_select'),
]
],
'network' => [
t('Network'),
[
'savedsearch',
t('Saved Searches'),
t('Save search terms for re-use'),
false,
get_config('feature_lock','savedsearch')
],
[
'filing',
t('Saved Folders'),
t('Ability to file posts under folders'),
false,
get_config('feature_lock','filing'),
],
[
'order_tab',
t('Alternate Stream Order'),
t('Ability to order the stream by last post date, last comment date or unthreaded activities'),
false,
get_config('feature_lock','order_tab')
],
[
'name_tab',
t('Contact Filter'),
t('Ability to display only posts of a selected contact'),
false,
get_config('feature_lock','name_tab')
],
[
'forums_tab',
t('Forum Filter'),
t('Ability to display only posts of a specific forum'),
false,
get_config('feature_lock','forums_tab')
],
[
'personal_tab',
t('Personal Posts Filter'),
t('Ability to display only posts that you\'ve interacted on'),
false,
get_config('feature_lock','personal_tab')
],
[
'affinity',
t('Affinity Tool'),
t('Filter stream activity by depth of relationships'),
false,
get_config('feature_lock','affinity')
],
[
'suggest',
t('Suggest Channels'),
t('Show friend and connection suggestions'),
false,
get_config('feature_lock','suggest')
],
[
'network_list_mode',
t('Use blog/list mode'),
t('Comments will be displayed separately'),
false,
get_config('feature_lock','network_list_mode'),
]
],
'photos' => [
t('Photos'),
[
'photo_location',
t('Photo Location'),
t('If location data is available on uploaded photos, link this to a map.'),
false,
get_config('feature_lock','photo_location'),
]
],
'profiles' => [
t('Profiles'),
[
'advanced_profiles',
t('Advanced Profiles'),
t('Additional profile sections and selections'),
false,
get_config('feature_lock','advanced_profiles')
],
[
'profile_export',
t('Profile Import/Export'),
t('Save and load profile details across sites/channels'),
false,
get_config('feature_lock','profile_export')
],
[
'multi_profiles',
t('Multiple Profiles'),
t('Ability to create multiple profiles'),
false,
get_config('feature_lock','multi_profiles')
]
]
];
$x = [ 'features' => $arr, ];
@@ -526,8 +438,6 @@ function get_features($filtered = true, $level = (-1)) {
$arr = $x['features'];
$techlevel = (($level >= 0) ? $level : get_account_techlevel());
// removed any locked features and remove the entire category if this makes it empty
if($filtered) {
@@ -538,9 +448,6 @@ function get_features($filtered = true, $level = (-1)) {
for($y = 0; $y < count($arr[$k]); $y ++) {
$disabled = false;
if(is_array($arr[$k][$y])) {
if($arr[$k][$y][5] > $techlevel) {
$disabled = true;
}
if($arr[$k][$y][4] !== false) {
$disabled = true;
}
@@ -561,3 +468,8 @@ function get_features($filtered = true, $level = (-1)) {
return $narr;
}
function get_module_features($module) {
$features = get_features(false);
return $features[$module];
}

View File

@@ -14,11 +14,11 @@ function group_add($uid,$name,$public = 0) {
// access lists. What we're doing here is reviving the dead group, but old content which
// was restricted to this group may now be seen by the new group members.
$z = q("SELECT * FROM groups WHERE id = %d LIMIT 1",
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
intval($r)
);
if(($z) && $z[0]['deleted']) {
q('UPDATE groups SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
notice( t('A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL);
}
return true;
@@ -28,13 +28,13 @@ function group_add($uid,$name,$public = 0) {
$dups = false;
$hash = random_string() . $name;
$r = q("SELECT id FROM groups WHERE hash = '%s' LIMIT 1", dbesc($hash));
$r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash));
if($r)
$dups = true;
} while($dups == true);
$r = q("INSERT INTO groups ( hash, uid, visible, gname )
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
VALUES( '%s', %d, %d, '%s' ) ",
dbesc($hash),
intval($uid),
@@ -53,7 +53,7 @@ function group_add($uid,$name,$public = 0) {
function group_rmv($uid,$name) {
$ret = false;
if(x($uid) && x($name)) {
$r = q("SELECT id, hash FROM groups WHERE uid = %d AND gname = '%s' LIMIT 1",
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -98,13 +98,13 @@ function group_rmv($uid,$name) {
}
// remove all members
$r = q("DELETE FROM group_member WHERE uid = %d AND gid = %d ",
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
intval($uid),
intval($group_id)
);
// remove group
$r = q("UPDATE groups SET deleted = 1 WHERE uid = %d AND gname = '%s'",
$r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
intval($uid),
dbesc($name)
);
@@ -121,7 +121,7 @@ function group_rmv($uid,$name) {
function group_byname($uid,$name) {
if((! $uid) || (! strlen($name)))
return false;
$r = q("SELECT * FROM groups WHERE uid = %d AND gname = '%s' LIMIT 1",
$r = q("SELECT * FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
intval($uid),
dbesc($name)
);
@@ -134,7 +134,7 @@ function group_byname($uid,$name) {
function group_rec_byhash($uid,$hash) {
if((! $uid) || (! strlen($hash)))
return false;
$r = q("SELECT * FROM groups WHERE uid = %d AND hash = '%s' LIMIT 1",
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
intval($uid),
dbesc($hash)
);
@@ -149,7 +149,7 @@ function group_rmv_member($uid,$name,$member) {
return false;
if(! ( $uid && $gid && $member))
return false;
$r = q("DELETE FROM group_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
intval($uid),
intval($gid),
dbesc($member)
@@ -169,7 +169,7 @@ function group_add_member($uid,$name,$member,$gid = 0) {
if((! $gid) || (! $uid) || (! $member))
return false;
$r = q("SELECT * FROM group_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
intval($uid),
intval($gid),
dbesc($member)
@@ -179,7 +179,7 @@ function group_add_member($uid,$name,$member,$gid = 0) {
// we indicate success because the group member was in fact created
// -- It was just created at another time
if(! $r)
$r = q("INSERT INTO group_member (uid, gid, xchan)
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
VALUES( %d, %d, '%s' ) ",
intval($uid),
intval($gid),
@@ -194,9 +194,9 @@ function group_add_member($uid,$name,$member,$gid = 0) {
function group_get_members($gid) {
$ret = array();
if(intval($gid)) {
$r = q("SELECT * FROM group_member
LEFT JOIN abook ON abook_xchan = group_member.xchan left join xchan on xchan_hash = abook_xchan
WHERE gid = %d AND abook_channel = %d and group_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
$r = q("SELECT * FROM pgrp_member
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
intval($gid),
intval(local_channel()),
intval(local_channel())
@@ -210,7 +210,7 @@ function group_get_members($gid) {
function group_get_members_xchan($gid) {
$ret = array();
if(intval($gid)) {
$r = q("SELECT xchan FROM group_member WHERE gid = %d AND uid = %d",
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
intval($gid),
intval(local_channel())
);
@@ -248,7 +248,7 @@ function mini_group_select($uid,$group = '') {
$grps = array();
$o = '';
$r = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval($uid)
);
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
@@ -274,13 +274,13 @@ function group_side($every="connections",$each="group",$edit = false, $group_id
$o = '';
if(! (local_channel() && feature_enabled(local_channel(),'groups'))) {
if(! (local_channel() && \Zotlabs\Lib\Apps::system_app_installed(local_channel(), 'Privacy Groups'))) {
return '';
}
$groups = array();
$r = q("SELECT * FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
intval($_SESSION['uid'])
);
$member_of = array();
@@ -361,7 +361,7 @@ function expand_groups($g) {
stringify_array_elms($x,true);
$groups = implode(',', $x);
if($groups) {
$r = q("SELECT xchan FROM group_member WHERE gid IN ( select id from groups where hash in ( $groups ))");
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
if($r) {
foreach($r as $rr) {
$ret[] = $rr['xchan'];
@@ -375,7 +375,7 @@ function expand_groups($g) {
function member_of($c) {
$r = q("SELECT groups.gname, groups.id FROM groups LEFT JOIN group_member ON group_member.gid = groups.id WHERE group_member.xchan = '%s' AND groups.deleted = 0 ORDER BY groups.gname ASC ",
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
dbesc($c)
);
@@ -385,7 +385,7 @@ function member_of($c) {
function groups_containing($uid,$c) {
$r = q("SELECT gid FROM group_member WHERE uid = %d AND group_member.xchan = '%s' ",
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
intval($uid),
dbesc($c)
);

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

@@ -24,6 +24,8 @@ function hubloc_store_lowlevel($arr) {
'hubloc_status' => ((array_key_exists('hubloc_status',$arr)) ? $arr['hubloc_status'] : 0),
'hubloc_url' => ((array_key_exists('hubloc_url',$arr)) ? $arr['hubloc_url'] : ''),
'hubloc_url_sig' => ((array_key_exists('hubloc_url_sig',$arr)) ? $arr['hubloc_url_sig'] : ''),
'hubloc_id_url' => ((array_key_exists('hubloc_id_url',$arr)) ? $arr['hubloc_id_url'] : ''),
'hubloc_site_id' => ((array_key_exists('hubloc_site_id',$arr)) ? $arr['hubloc_site_id'] : ''),
'hubloc_host' => ((array_key_exists('hubloc_host',$arr)) ? $arr['hubloc_host'] : ''),
'hubloc_callback' => ((array_key_exists('hubloc_callback',$arr)) ? $arr['hubloc_callback'] : ''),
'hubloc_connect' => ((array_key_exists('hubloc_connect',$arr)) ? $arr['hubloc_connect'] : ''),

View File

@@ -93,7 +93,8 @@ function import_channel($channel, $account_id, $seize, $newname = '') {
'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
'channel_a_delegate', 'perm_limits', 'channel_password', 'channel_salt',
'channel_moved'
'channel_moved', 'channel_primary', 'channel_removed', 'channel_deleted',
'channel_system'
];
$clean = array();
@@ -234,7 +235,7 @@ function import_hublocs($channel, $hublocs, $seize, $moving = false) {
if(($x = zot_gethub($arr,false)) === false) {
unset($hubloc['hubloc_id']);
create_table_from_array('hubloc', $hubloc);
hubloc_store_lowlevel($hubloc);
}
else {
q("UPDATE hubloc set hubloc_primary = %d, hubloc_deleted = %d where hubloc_id = %d",

View File

@@ -4,7 +4,13 @@
* @brief Items related functions.
*/
use Zotlabs\Lib as Zlib;
use Zotlabs\Lib\Enotify;
use Zotlabs\Lib\MarkdownSoap;
use Zotlabs\Lib\MessageFilter;
use Zotlabs\Lib\IConfig;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Access\AccessList;
use Zotlabs\Daemon\Master;
require_once('include/bbcode.php');
require_once('include/oembed.php');
@@ -234,10 +240,11 @@ function can_comment_on_post($observer_xchan, $item) {
// logger('Comment_policy: ' . $item['comment_policy'], LOGGER_DEBUG);
$x = [
'observer_hash' => $observer_xchan,
'item' => $item,
'allowed' => 'unset'
'observer_hash' => $observer_xchan,
'item' => $item,
'allowed' => 'unset'
];
/**
* @hooks can_comment_on_post
* Called when deciding whether or not to present a comment box for a post.
@@ -245,26 +252,34 @@ function can_comment_on_post($observer_xchan, $item) {
* * \e array \b item
* * \e boolean \b allowed - return value
*/
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':
@@ -276,17 +291,22 @@ function can_comment_on_post($observer_xchan, $item) {
case 'any connections':
case 'contacts':
case '':
if(array_key_exists('owner',$item) && get_abconfig($item['uid'],$item['owner']['abook_xchan'],'their_perms','post_comments')) {
return true;
if(local_channel() && get_abconfig(local_channel(),$item['owner_xchan'],'their_perms','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;
}
@@ -365,7 +385,7 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
return $ret;
}
$arr['public_policy'] = ((array_key_exists('public_policy',$arr)) ? escape_tags($arr['public_policy']) : map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true));
$arr['public_policy'] = ((array_key_exists('public_policy',$arr)) ? escape_tags($arr['public_policy']) : map_scope(PermissionLimits::Get($channel['channel_id'],'view_stream'),true));
if($arr['public_policy'])
$arr['item_private'] = 1;
@@ -393,7 +413,7 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
$arr['deny_gid'] = $channel['channel_deny_gid'];
}
$arr['comment_policy'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments'));
$arr['comment_policy'] = map_scope(PermissionLimits::Get($channel['channel_id'],'post_comments'));
if ((! $arr['plink']) && (intval($arr['item_thread_top']))) {
$arr['plink'] = substr(z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . urlencode($arr['mid']),0,190);
@@ -432,7 +452,7 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
}
if($post_id && $deliver) {
Zotlabs\Daemon\Master::Summon(array('Notifier','activity',$post_id));
Master::Summon([ 'Notifier','activity',$post_id ]);
}
$ret['success'] = true;
@@ -730,7 +750,7 @@ function get_item_elements($x,$allow_code = false) {
// was generated on the escaped content.
if($arr['mimetype'] === 'text/markdown')
$arr['body'] = \Zotlabs\Lib\MarkdownSoap::unescape($arr['body']);
$arr['body'] = MarkdownSoap::unescape($arr['body']);
if(array_key_exists('revision',$x)) {
@@ -989,7 +1009,7 @@ function encode_item($item,$mirror = false) {
);
if($r)
$comment_scope = \Zotlabs\Access\PermissionLimits::Get($item['uid'],'post_comments');
$comment_scope = PermissionLimits::Get($item['uid'],'post_comments');
else
$comment_scope = 0;
@@ -2425,7 +2445,7 @@ function send_status_notifications($post_id,$item) {
return;
Zlib\Enotify::submit(array(
Enotify::submit(array(
'type' => NOTIFY_COMMENT,
'from_xchan' => $item['author_xchan'],
'to_xchan' => $r[0]['channel_hash'],
@@ -2518,7 +2538,7 @@ function tag_deliver($uid, $item_id) {
$verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
if($poke_notify) {
Zlib\Enotify::submit(array(
Enotify::submit(array(
'to_xchan' => $u[0]['channel_hash'],
'from_xchan' => $item['author_xchan'],
'type' => NOTIFY_POKE,
@@ -2672,7 +2692,7 @@ function tag_deliver($uid, $item_id) {
* Kill two birds with one stone. As long as we're here, send a mention notification.
*/
Zlib\Enotify::submit(array(
Enotify::submit(array(
'to_xchan' => $u[0]['channel_hash'],
'from_xchan' => $item['author_xchan'],
'type' => NOTIFY_TAGSELF,
@@ -2974,7 +2994,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent) {
$private = (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0);
$new_public_policy = map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_stream'),true);
$new_public_policy = map_scope(PermissionLimits::Get($channel['channel_id'],'view_stream'),true);
if((! $private) && $new_public_policy)
$private = 1;
@@ -3017,7 +3037,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent) {
dbesc($channel['channel_deny_gid']),
intval($private),
dbesc($new_public_policy),
dbesc(map_scope(\Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'post_comments'))),
dbesc(map_scope(PermissionLimits::Get($channel['channel_id'],'post_comments'))),
dbesc($title),
dbesc($body),
intval($item_wall),
@@ -3026,7 +3046,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent) {
);
if($r)
Zotlabs\Daemon\Master::Summon(array('Notifier','tgroup',$item_id));
Master::Summon([ 'Notifier','tgroup',$item_id ]);
else {
logger('start_delivery_chain: failed to update item');
// reset the source xchan to prevent loops
@@ -3091,7 +3111,7 @@ function check_item_source($uid, $item) {
return true;
}
if (\Zotlabs\Lib\MessageFilter::evaluate($item, $r[0]['src_patt'], EMPTY_STR)) {
if (MessageFilter::evaluate($item, $r[0]['src_patt'], EMPTY_STR)) {
logger('source: text filter success');
return true;
}
@@ -3114,7 +3134,7 @@ function post_is_importable($item,$abook) {
if(! ($abook['abook_incl'] || $abook['abook_excl']))
return true;
return \Zotlabs\Lib\MessageFilter::evaluate($item,$abook['abook_incl'],$abook['abook_excl']);
return MessageFilter::evaluate($item,$abook['abook_incl'],$abook['abook_excl']);
}
@@ -3250,7 +3270,7 @@ function mail_store($arr) {
'otype' => 'mail'
);
Zlib\Enotify::submit($notif_params);
Enotify::submit($notif_params);
}
if($arr['conv_guid']) {
@@ -3533,8 +3553,9 @@ function drop_items($items,$interactive = false,$stage = DROPITEM_NORMAL,$force
// multiple threads may have been deleted, send an expire notification
if($uid)
Zotlabs\Daemon\Master::Summon(array('Notifier','expire',$uid));
if($uid) {
Master::Summon([ 'Notifier','expire',$uid ]);
}
}
@@ -3642,8 +3663,9 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal
// We'll rely on the undocumented behaviour that DROPITEM_PHASE1 is (hopefully) only
// set if we know we're going to send delete notifications out to others.
if((intval($item['item_wall']) && ($stage != DROPITEM_PHASE2)) || ($stage == DROPITEM_PHASE1))
Zotlabs\Daemon\Master::Summon(array('Notifier','drop',$notify_id));
if((intval($item['item_wall']) && ($stage != DROPITEM_PHASE2)) || ($stage == DROPITEM_PHASE1)) {
Master::Summon([ 'Notifier','drop',$notify_id ]);
}
goaway(z_root() . '/' . $_SESSION['return_url']);
}
@@ -3767,21 +3789,34 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) {
* @brief Return the first post date.
*
* @param int $uid
* @param boolean $wall (optional) default false
* @param boolean $wall (optional) no longer used
* @return string|boolean date string, otherwise false
*/
function first_post_date($uid, $wall = false) {
$wall_sql = (($wall) ? " and item_wall = 1 " : "" );
$item_normal = item_normal();
$sql_extra = '';
switch(App::$module) {
case 'articles':
$sql_extra .= " and item_type = 7 ";
$item_normal = " and item.item_hidden = 0 and item.item_type = 7 and item.item_deleted = 0
and item.item_unpublished = 0 and item.item_delayed = 0 and item.item_pending_remove = 0
and item.item_blocked = 0 ";
break;
case 'channel':
$sql_extra = " and item_wall = 1 ";
default:
$item_normal = item_normal();
break;
}
$r = q("select id, created from item
where uid = %d and id = parent $item_normal $wall_sql
where uid = %d and id = parent $item_normal $sql_extra
order by created asc limit 1",
intval($uid)
);
if($r) {
// logger('first_post_date: ' . $r[0]['id'] . ' ' . $r[0]['created'], LOGGER_DATA);
return substr(datetime_convert('',date_default_timezone_get(),$r[0]['created']),0,10);
}
@@ -3962,6 +3997,7 @@ function zot_feed($uid, $observer_hash, $arr) {
$result = array();
$mindate = null;
$message_id = null;
$wall = true;
require_once('include/security.php');
@@ -3973,6 +4009,10 @@ function zot_feed($uid, $observer_hash, $arr) {
$message_id = $arr['message_id'];
}
if(array_key_exists('wall',$arr)) {
$wall = intval($arr['wall']);
}
if(! $mindate)
$mindate = NULL_DATE;
@@ -4001,6 +4041,10 @@ function zot_feed($uid, $observer_hash, $arr) {
$limit = '';
}
if($wall) {
$sql_extra .= " and item_wall = 1 ";
}
$items = [];
@@ -4013,7 +4057,6 @@ function zot_feed($uid, $observer_hash, $arr) {
$r = q("SELECT parent, postopts FROM item
WHERE uid IN ( %s )
AND item_wall = 1
AND item_private = 0
$item_normal
$sql_extra ORDER BY created ASC $limit",
@@ -4023,7 +4066,6 @@ function zot_feed($uid, $observer_hash, $arr) {
else {
$r = q("SELECT parent, postopts FROM item
WHERE uid = %d
AND item_wall = 1
$item_normal
$sql_extra ORDER BY created ASC $limit",
intval($uid)
@@ -4117,7 +4159,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
$sql_extra .= protect_sprintf(term_query('item', $arr['cat'], TERM_CATEGORY));
if($arr['gid'] && $uid) {
$r = q("SELECT * FROM groups WHERE id = %d AND uid = %d LIMIT 1",
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
intval($arr['group']),
intval($uid)
);
@@ -4379,7 +4421,7 @@ function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remo
// sixteen bytes of the mid - which makes the link portable and not quite as daunting
// as the entire mid. If it were the post_id the link would be less portable.
\Zotlabs\Lib\IConfig::Set(
IConfig::Set(
intval($post_id),
'system',
$page_type,
@@ -4512,7 +4554,7 @@ function send_profile_photo_activity($channel,$photo,$profile) {
$arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext;
$acl = new Zotlabs\Access\AccessList($channel);
$acl = new AccessList($channel);
$x = $acl->get();
$arr['allow_cid'] = $x['allow_cid'];
@@ -4743,7 +4785,7 @@ function item_create_edit_activity($post) {
}
}
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'edit_activity', $post_id));
Master::Summon([ 'Notifier', 'edit_activity', $post_id ]);
}
/**

View File

@@ -38,6 +38,15 @@ function js_strings() {
// using the defaults set below if left untranslated, empty strings if
// translated to "NONE" and the corresponding language strings
// if translated to anything else
'minutes' => tt('%d minutes', '%d minutes', '%d'),
'hours' => tt('about %d hours', 'about %d hours', '%d'),
'days' => tt('%d days', '%d days', '%d'),
'months' => tt('%d months', '%d months', '%d'),
'years' => tt('%d years', '%d years', '%d'),
// get plural function code
'plural_func' => tf(),
'$t01' => ((t('timeago.prefixAgo') == 'timeago.prefixAgo') ? '' : ((t('timeago.prefixAgo') == 'NONE') ? '' : t('timeago.prefixAgo'))),
'$t02' => ((t('timeago.prefixFromNow') == 'timeago.prefixFromNow') ? '' : ((t('timeago.prefixFromNow') == 'NONE') ? '' : t('timeago.prefixFromNow'))),
'$t03' => ((t('timeago.suffixAgo') == 'timeago.suffixAgo') ? 'ago' : ((t('timeago.suffixAgo') == 'NONE') ? '' : t('timeago.suffixAgo'))),
@@ -46,15 +55,15 @@ function js_strings() {
// translatable main strings for jquery.timeago
'$t05' => t('less than a minute'),
'$t06' => t('about a minute'),
'$t07' => t('%d minutes'),
'$t07' => ta('%d minutes'),
'$t08' => t('about an hour'),
'$t09' => t('about %d hours'),
'$t09' => ta('about %d hours'),
'$t10' => t('a day'),
'$t11' => t('%d days'),
'$t11' => ta('%d days'),
'$t12' => t('about a month'),
'$t13' => t('%d months'),
'$t13' => ta('%d months'),
'$t14' => t('about a year'),
'$t15' => t('%d years'),
'$t15' => ta('%d years'),
'$t16' => t(' '), // wordSeparator
'$t17' => ((t('timeago.numbers') != 'timeago.numbers') ? t('timeago.numbers') : '[]'),

View File

@@ -254,6 +254,32 @@ function tt($singular, $plural, $count, $ctx = ''){
}
}
/**
* @brief Return slash separated string of plurals translation forms
*
* @param string $k key in translations array
* @return string
*/
function ta($k){
$t = App::$strings[$k];
if (is_array($t))
$t = implode("/", $t);
return ($t == "" ? $k : $t);
}
/**
* @brief Return string_plural_select_xx function code
*
* @return string
*/
function tf() {
$s = "plural_function_code";
return (x(App::$strings, $s) ? App::$strings[$s] : "0");
}
/**
* @brief Provide a fallback which will not collide with a function defined in
* any language file.

View File

@@ -5,7 +5,11 @@
*/
use Michelf\MarkdownExtra;
use League\HTMLToMarkdown\HtmlConverter;
use League\HTMLToMarkdown\Environment;
use League\HTMLToMarkdown\Converter\ConverterInterface;
use League\HTMLToMarkdown\ElementInterface;
require_once("include/oembed.php");
require_once("include/event.php");
@@ -74,11 +78,14 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) {
// Convert everything that looks like a link to a link
if($use_zrl) {
$s = str_replace(['[img', '/img]'], ['[zmg', '/zmg]'], $s);
$s = preg_replace("/([^\]\=\{]|^)(https?\:\/\/)([a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ismu", '$1[zrl=$2$3]$2$3[/zrl]',$s);
if (strpos($s,'[/img]') !== false) {
$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);
}
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
@@ -96,6 +103,41 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) {
return $s;
}
function use_zrl_cb_link($match) {
$res = '';
$is_zid = is_matrix_url(trim($match[0]));
if($is_zid)
$res = $match[1] . '[zrl=' . $match[2] . $match[3] . ']' . $match[2] . $match[3] . '[/zrl]';
else
$res = $match[1] . '[url=' . $match[2] . $match[3] . ']' . $match[2] . $match[3] . '[/url]';
return $res;
}
function use_zrl_cb_img($match) {
$res = '';
$is_zid = is_matrix_url(trim($match[1]));
if($is_zid)
$res = '[zmg]' . $match[1] . '[/zmg]';
else
$res = $match[0];
return $res;
}
function use_zrl_cb_img_x($match) {
$res = '';
$is_zid = is_matrix_url(trim($match[3]));
if($is_zid)
$res = '[zmg=' . $match[1] . 'x' . $match[2] . ']' . $match[3] . '[/zmg]';
else
$res = $match[0];
return $res;
}
/**
* @brief
@@ -213,6 +255,9 @@ function bb_to_markdown($Text, $options = []) {
$Text = html2markdown($Text);
//html2markdown adds backslashes infront of hashes after a new line. remove them
$Text = str_replace("\n\#", "\n#", $Text);
// It also adds backslashes to our attempt at getting around the html entity preservation for some weird reason.
//$Text = str_replace(array('&\\_lt\\_;','&\\_gt\\_;','&\\_amp\\_;'),array('&lt;','&gt;','&amp;'),$Text);
@@ -248,9 +293,14 @@ function bb_to_markdown($Text, $options = []) {
* @param string $html The HTML code to convert
* @return string Markdown representation of the given HTML text, empty on error
*/
function html2markdown($html) {
function html2markdown($html,$options = []) {
$markdown = '';
$converter = new HtmlConverter();
$internal_errors = libxml_use_internal_errors(true);
$environment = Environment::createDefaultEnvironment($options);
$environment->addConverter(new TableConverter());
$converter = new HtmlConverter($environment);
try {
$markdown = $converter->convert($html);
@@ -258,5 +308,77 @@ function html2markdown($html) {
logger("Invalid HTML. HTMLToMarkdown library threw an exception.");
}
libxml_use_internal_errors($internal_errors);
return $markdown;
}
// Tables are not an official part of the markdown specification.
// This interface was suggested as a workaround.
// author: Mark Hamstra
// https://github.com/Mark-H/Docs
class TableConverter implements ConverterInterface
{
/**
* @param ElementInterface $element
*
* @return string
*/
public function convert(ElementInterface $element)
{
switch ($element->getTagName()) {
case 'tr':
$line = [];
$i = 1;
foreach ($element->getChildren() as $td) {
$i++;
$v = $td->getValue();
$v = trim($v);
if ($i % 2 === 0 || $v !== '') {
$line[] = $v;
}
}
return '| ' . implode(' | ', $line) . " |\n";
case 'td':
case 'th':
return trim($element->getValue());
case 'tbody':
return trim($element->getValue());
case 'thead':
$headerLine = reset($element->getChildren())->getValue();
$headers = explode(' | ', trim(trim($headerLine, "\n"), '|'));
$hr = [];
foreach ($headers as $td) {
$length = strlen(trim($td)) + 2;
$hr[] = str_repeat('-', $length > 3 ? $length : 3);
}
$hr = '|' . implode('|', $hr) . '|';
return $headerLine . $hr . "\n";
case 'table':
$inner = $element->getValue();
if (strpos($inner, '-----') === false) {
$inner = explode("\n", $inner);
$single = explode(' | ', trim($inner[0], '|'));
$hr = [];
foreach ($single as $td) {
$length = strlen(trim($td)) + 2;
$hr[] = str_repeat('-', $length > 3 ? $length : 3);
}
$hr = '|' . implode('|', $hr) . '|';
array_splice($inner, 1, 0, $hr);
$inner = implode("\n", $inner);
}
return trim($inner) . "\n\n";
}
return $element->getValue();
}
/**
* @return string[]
*/
public function getSupportedTags()
{
return array('table', 'tr', 'thead', 'td', 'tbody');
}
}

View File

@@ -4,6 +4,7 @@
require_once('include/crypto.php');
require_once('include/attach.php');
require_once('include/msglib.php');
function mail_prepare_binary($item) {
@@ -498,11 +499,8 @@ function private_messages_drop($channel_id, $messageitem_id, $drop_conversation
}
else {
xchan_mail_query($x[0]);
$x[0]['mail_deleted'] = true;
$r = q("DELETE FROM mail WHERE id = %d AND channel_id = %d",
intval($messageitem_id),
intval($channel_id)
);
$x[0]['mail_deleted'] = true;
msg_drop($messageitem_id, $channel_id, $x[0]['conv_guid']);
build_sync_packet($channel_id,array('mail' => array(encode_mail($x,true))));
return true;
}

28
include/msglib.php Normal file
View File

@@ -0,0 +1,28 @@
<?php
/* Common private message processing functions */
function msg_drop($message_id, $channel_id, $conv_guid) {
// Delete message
$r = q("DELETE FROM mail WHERE id = %d AND channel_id = %d",
intval($message_id),
intval($channel_id)
);
// Get new first message...
$r = q("SELECT mid, parent_mid FROM mail WHERE conv_guid = '%s' AND channel_id = %d ORDER BY id ASC LIMIT 1",
dbesc($conv_guid),
intval($channel_id)
);
// ...and if wasn't first before...
if ($r[0]['mid'] != $r[0]['parent_mid']) {
// ...refer whole thread to it
q("UPDATE mail SET parent_mid = '%s', mail_isreply = abs(mail_isreply - 1) WHERE conv_guid = '%s' AND channel_id = %d",
dbesc($r[0]['mid']),
dbesc($conv_guid),
intval($channel_id)
);
}
}

View File

@@ -1,11 +1,11 @@
<?php /** @file */
use \Zotlabs\Lib as Zlib;
use \Zotlabs\Lib\Apps;
use \Zotlabs\Lib\Chatroom;
require_once('include/security.php');
require_once('include/menu.php');
function nav($template = 'default') {
/**
@@ -60,8 +60,6 @@ function nav($template = 'default') {
//we could additionally use this to display important system notifications e.g. for updates
));
$techlevel = get_account_techlevel();
// nav links: array of array('href', 'text', 'extra css classes', 'title')
$nav = [];
@@ -93,7 +91,7 @@ function nav($template = 'default') {
if(! $_SESSION['delegate']) {
$nav['manage'] = array('manage', t('Channel Manager'), "", t('Manage your channels'),'manage_nav_btn');
}
if(feature_enabled(local_channel(),'groups'))
if(Apps::system_app_installed(local_channel(), 'Privacy Groups'))
$nav['group'] = array('group', t('Privacy Groups'),"", t('Manage your privacy groups'),'group_nav_btn');
$nav['settings'] = array('settings', t('Settings'),"", t('Account/Channel Settings'),'settings_nav_btn');
@@ -199,40 +197,60 @@ function nav($template = 'default') {
// turned off until somebody discovers this and figures out a good location for it.
$powered_by = '';
$url = '';
$settings_url = '';
if(App::$profile_uid && App::$nav_sel['raw_name']) {
$active_app = q("SELECT app_url FROM app WHERE app_channel = %d AND app_name = '%s' LIMIT 1",
intval(App::$profile_uid),
dbesc(App::$nav_sel['raw_name'])
);
if($active_app) {
$url = $active_app[0]['app_url'];
if(strpos($active_app[0]['app_url'], ',')) {
$urls = explode(',', $active_app[0]['app_url']);
$url = trim($urls[0]);
if($is_owner)
$settings_url = trim($urls[1]);
}
else {
$url = $active_app[0]['app_url'];
}
}
}
if(! $settings_url && isset(App::$nav_sel['settings_url']))
$settings_url = App::$nav_sel['settings_url'];
//app bin
if($is_owner) {
//daily system apps import
if(get_pconfig(local_channel(), 'system','import_system_apps') !== datetime_convert('UTC','UTC','now','Y-m-d')) {
Zlib\Apps::import_system_apps();
Apps::import_system_apps();
set_pconfig(local_channel(), 'system','import_system_apps', datetime_convert('UTC','UTC','now','Y-m-d'));
}
if(get_pconfig(local_channel(), 'system','force_import_system_apps') !== STD_VERSION) {
Apps::import_system_apps();
set_pconfig(local_channel(), 'system','force_import_system_apps', STD_VERSION);
}
$syslist = array();
$list = Zlib\Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
$list = Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
if($list) {
foreach($list as $li) {
$syslist[] = Zlib\Apps::app_encode($li);
$syslist[] = Apps::app_encode($li);
}
}
Zlib\Apps::translate_system_apps($syslist);
Apps::translate_system_apps($syslist);
}
else {
$syslist = Zlib\Apps::get_system_apps(true);
$syslist = Apps::get_system_apps(true);
}
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
$syslist = Zlib\Apps::app_order(local_channel(),$syslist);
$syslist = Apps::app_order(local_channel(),$syslist);
foreach($syslist as $app) {
if(\App::$nav_sel['name'] == $app['name'])
@@ -240,18 +258,18 @@ function nav($template = 'default') {
if($is_owner) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
$navbar_apps[] = Zlib\Apps::app_render($app,'navbar');
$navbar_apps[] = Apps::app_render($app,'navbar');
}
else {
$nav_apps[] = Zlib\Apps::app_render($app,'nav');
$nav_apps[] = Apps::app_render($app,'nav');
}
}
elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
$navbar_apps[] = Zlib\Apps::app_render($app,'navbar');
$navbar_apps[] = Apps::app_render($app,'navbar');
}
else {
$nav_apps[] = Zlib\Apps::app_render($app,'nav');
$nav_apps[] = Apps::app_render($app,'nav');
}
}
}
@@ -289,7 +307,8 @@ function nav($template = 'default') {
'$addapps' => t('Add Apps'),
'$orderapps' => t('Arrange Apps'),
'$sysapps_toggle' => t('Toggle System Apps'),
'$url' => (($url) ? $url : App::$cmd)
'$url' => (($url) ? $url : z_root() . '/' . App::$cmd),
'$settings_url' => $settings_url
));
if(x($_SESSION, 'reload_avatar') && $observer) {
@@ -311,15 +330,18 @@ function nav($template = 'default') {
* Set a menu item in navbar as selected
*
*/
function nav_set_selected($item){
App::$nav_sel['raw_name'] = $item;
$item = ['name' => $item];
Zlib\Apps::translate_system_apps($item);
function nav_set_selected($raw_name, $settings_url = ''){
App::$nav_sel['raw_name'] = $raw_name;
$item = ['name' => $raw_name];
Apps::translate_system_apps($item);
App::$nav_sel['name'] = $item['name'];
if($settings_url)
App::$nav_sel['settings_url'] = z_root() . '/' . $settings_url;
}
function channel_apps($is_owner = false, $nickname = null) {
// Don't provide any channel apps if we're running as the sys channel
@@ -419,8 +441,8 @@ function channel_apps($is_owner = false, $nickname = null) {
}
if ($p['chat'] && feature_enabled($uid,'ajaxchat')) {
$has_chats = ZLib\Chatroom::list_count($uid);
if ($p['chat'] && Apps::system_app_installed($uid,'Chatrooms')) {
$has_chats = Chatroom::list_count($uid);
if ($has_chats) {
$tabs[] = [
'label' => t('Chatrooms'),
@@ -445,7 +467,7 @@ function channel_apps($is_owner = false, $nickname = null) {
];
}
if($p['view_pages'] && feature_enabled($uid,'cards')) {
if($p['view_pages'] && Apps::system_app_installed($uid, 'Cards')) {
$tabs[] = [
'label' => t('Cards'),
'url' => z_root() . '/cards/' . $nickname ,
@@ -456,7 +478,7 @@ function channel_apps($is_owner = false, $nickname = null) {
];
}
if($p['view_pages'] && feature_enabled($uid,'articles')) {
if($p['view_pages'] && Apps::system_app_installed($uid, 'Articles')) {
$tabs[] = [
'label' => t('Articles'),
'url' => z_root() . '/articles/' . $nickname ,
@@ -468,7 +490,7 @@ function channel_apps($is_owner = false, $nickname = null) {
}
if($has_webpages && feature_enabled($uid,'webpages')) {
if($has_webpages && Apps::system_app_installed($uid, 'Webpages')) {
$tabs[] = [
'label' => t('Webpages'),
'url' => z_root() . '/page/' . $nickname . '/home',
@@ -480,21 +502,19 @@ function channel_apps($is_owner = false, $nickname = null) {
}
if ($p['view_wiki']) {
if(feature_enabled($uid,'wiki') && (get_account_techlevel($account_id) > 3)) {
$tabs[] = [
'label' => t('Wikis'),
'url' => z_root() . '/wiki/' . $nickname,
'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
'title' => t('Wiki'),
'id' => 'wiki-tab',
'icon' => 'pencil-square-o'
];
}
if ($p['view_wiki'] && Apps::system_app_installed($uid, 'Wiki')) {
$tabs[] = [
'label' => t('Wikis'),
'url' => z_root() . '/wiki/' . $nickname,
'sel' => ((argv(0) == 'wiki') ? 'active' : ''),
'title' => t('Wiki'),
'id' => 'wiki-tab',
'icon' => 'pencil-square-o'
];
}
$arr = array('is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => (($tab) ? $tab : false), 'tabs' => $tabs);
call_hooks('profile_tabs', $arr);
call_hooks('channel_apps', $arr);
return replace_macros(get_markup_template('profile_tabs.tpl'),

View File

@@ -48,6 +48,10 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
if(($redirects > 8) || (! $ch))
return $ret;
if(! array_key_exists('request_target',$opts)) {
$opts['request_target'] = 'get ' . get_request_string($url);
}
@curl_setopt($ch, CURLOPT_HEADER, true);
@curl_setopt($ch, CURLINFO_HEADER_OUT, true);
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
@@ -157,7 +161,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
if($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307 || $http_code == 308) {
$matches = array();
preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
preg_match('/(Location:|URI:)(.*?)\n/i', $header, $matches);
$newurl = trim(array_pop($matches));
if(strpos($newurl,'/') === 0)
$newurl = $url . $newurl;
@@ -179,6 +183,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
}
$ret['body'] = substr($s,strlen($header));
$ret['header'] = $header;
$ret['request_target'] = $opts['request_target'];
if(x($opts,'debug')) {
$ret['debug'] = $curl_info;
@@ -227,6 +232,10 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
if(($redirects > 8) || (! $ch))
return $ret;
if(! array_key_exists('request_target',$opts)) {
$opts['request_target'] = 'get ' . get_request_string($url);
}
@curl_setopt($ch, CURLOPT_HEADER, true);
@curl_setopt($ch, CURLINFO_HEADER_OUT, true);
@curl_setopt($ch, CURLOPT_CAINFO, get_capath());
@@ -359,6 +368,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
$ret['body'] = substr($s, strlen($header));
$ret['header'] = $header;
$ret['request_target'] = $opts['request_target'];
if(x($opts,'debug')) {
$ret['debug'] = $curl_info;
@@ -2042,6 +2052,22 @@ function jsonld_document_loader($url) {
require_once('library/jsonld/jsonld.php');
$recursion = 0;
$x = debug_backtrace();
if($x) {
foreach($x as $n) {
if($n['function'] === __FUNCTION__) {
$recursion ++;
}
}
}
if($recursion > 5) {
logger('jsonld bomb detected at: ' . $url);
killme();
}
$cachepath = 'store/[data]/ldcache';
if(! is_dir($cachepath))
os_mkdir($cachepath, STORAGE_DEFAULT_PERMISSIONS, true);
@@ -2064,3 +2090,17 @@ function jsonld_document_loader($url) {
return [];
}
/**
* @brief Given a URL, return everything after the host portion.
* example https://foobar.com/gravy?g=5&y=6
* returns /gravy?g=5&y=6
* result always returns the leading slash
*/
function get_request_string($url) {
$a = explode('/',$url,4);
return '/' . ((count($a) > 3) ? $a[3] : EMPTY_STR);
}

View File

@@ -16,11 +16,14 @@ require_once('include/security.php');
*
* @param int $uid The channel_id associated with the resource owner
* @param string $observer_xchan The xchan_hash representing the observer
* @param bool $internal_use (default true)
* @param bool $check_siteblock (default true)
* if false, bypass check for "Block Public" on the site
* @param bool $default_ignored (default true)
* if false, lie and pretend the ignored person has permissions you are ignoring (used in channel discovery)
*
* @returns array of all permissions, key is permission name, value is true or false
*/
function get_all_perms($uid, $observer_xchan, $internal_use = true) {
function get_all_perms($uid, $observer_xchan, $check_siteblock = true, $default_ignored = true) {
$api = App::get_oauth_key();
if($api)
@@ -111,7 +114,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
$blocked_anon_perms = \Zotlabs\Access\Permissions::BlockedAnonPerms();
if(($x) && ($internal_use) && in_array($perm_name,$blocked_anon_perms) && intval($x[0]['abook_ignored'])) {
if(($x) && ($default_ignored) && in_array($perm_name,$blocked_anon_perms) && intval($x[0]['abook_ignored'])) {
$ret[$perm_name] = false;
continue;
}
@@ -119,7 +122,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
// system is blocked to anybody who is not authenticated
if((! $observer_xchan) && intval(get_config('system', 'block_public'))) {
if(($check_siteblock) && (! $observer_xchan) && intval(get_config('system', 'block_public'))) {
$ret[$perm_name] = false;
continue;
}
@@ -251,9 +254,11 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) {
* @param int $uid The channel_id associated with the resource owner
* @param string $observer_xchan The xchan_hash representing the observer
* @param string $permission
* @param boolean $check_siteblock (default true)
* if false bypass check for "Block Public" at the site level
* @return bool true if permission is allowed for observer on channel
*/
function perm_is_allowed($uid, $observer_xchan, $permission) {
function perm_is_allowed($uid, $observer_xchan, $permission, $check_siteblock = true) {
$api = App::get_oauth_key();
if($api)
@@ -326,7 +331,7 @@ function perm_is_allowed($uid, $observer_xchan, $permission) {
// system is blocked to anybody who is not authenticated
if((! $observer_xchan) && intval(get_config('system', 'block_public')))
if(($check_siteblock) && (! $observer_xchan) && intval(get_config('system', 'block_public')))
return false;
// Check if this $uid is actually the $observer_xchan

View File

@@ -14,17 +14,17 @@
* @param bool $uninstall uninstall plugin
*/
function handleerrors_plugin($plugin,$notice,$log,$uninstall=false){
logger("Addons: [" . $plugin . "] Error: ".$log, LOGGER_ERROR);
if ($notice != '') {
notice("[" . $plugin . "] Error: ".$notice, LOGGER_ERROR);
}
logger("Addons: [" . $plugin . "] Error: ".$log, LOGGER_ERROR);
if ($notice != '') {
notice("[" . $plugin . "] Error: ".$notice, LOGGER_ERROR);
}
if ($uninstall) {
$idx = array_search($plugin, \App::$plugins);
unset(\App::$plugins[$idx]);
uninstall_plugin($plugin);
set_config("system","addon", implode(", ",\App::$plugins));
}
if ($uninstall) {
$idx = array_search($plugin, \App::$plugins);
unset(\App::$plugins[$idx]);
uninstall_plugin($plugin);
set_config("system","addon", implode(", ",\App::$plugins));
}
}
/**
@@ -109,11 +109,16 @@ function install_plugin($plugin) {
$plugin_admin = (function_exists($plugin . '_plugin_admin') ? 1 : 0);
q("INSERT INTO addon (aname, installed, tstamp, plugin_admin) VALUES ( '%s', 1, %d , %d ) ",
dbesc($plugin),
intval($t),
$plugin_admin
$d = q("select * from addon where aname = '%s' limit 1",
dbesc($plugin)
);
if(! $d) {
q("INSERT INTO addon (aname, installed, tstamp, plugin_admin) VALUES ( '%s', 1, %d , %d ) ",
dbesc($plugin),
intval($t),
$plugin_admin
);
}
load_plugin($plugin);
}
@@ -206,19 +211,19 @@ function reload_plugins() {
if(function_exists($pl . '_unload')) {
$func = $pl . '_unload';
try {
$func();
$func();
} catch (Exception $e) {
handleerrors_plugin($plugin,"","UNLOAD FAILED (uninstalling) : ".$e->getMessage(),true);
continue;
continue;
}
}
if(function_exists($pl . '_load')) {
$func = $pl . '_load';
try {
$func();
$func();
} catch (Exception $e) {
handleerrors_plugin($plugin,"","LOAD FAILED (uninstalling): ".$e->getMessage(),true);
continue;
continue;
}
}
q("UPDATE addon SET tstamp = %d WHERE id = %d",
@@ -366,28 +371,47 @@ function unregister_hook($hook, $file, $function) {
return $r;
}
//
// It might not be obvious but themes can manually add hooks to the App::$hooks
// array in their theme_init() and use this to customise the app behaviour.
// UPDATE: use insert_hook($hookname,$function_name) to do this
//
/**
* @brief loads all active hooks into memory
* alters: App::$hooks
* Called during initialisation
* Duplicated hooks are removed and the duplicates ignored
*
* It might not be obvious but themes can manually add hooks to the App::$hooks
* array in their theme_init() and use this to customise the app behaviour.
* use insert_hook($hookname,$function_name) to do this.
*/
function load_hooks() {
App::$hooks = array();
App::$hooks = [];
$r = q("SELECT * FROM hook WHERE true ORDER BY priority DESC");
if($r) {
foreach($r as $rr) {
if(! array_key_exists($rr['hook'],App::$hooks))
App::$hooks[$rr['hook']] = array();
App::$hooks[$rr['hook']][] = array($rr['file'],$rr['fn'],$rr['priority'],$rr['hook_version']);
foreach($r as $rv) {
$duplicated = false;
if(! array_key_exists($rv['hook'],App::$hooks)) {
App::$hooks[$rv['hook']] = [];
}
else {
foreach(App::$hooks[$rv['hook']] as $h) {
if($h[0] === $rv['file'] && $h[1] === $rv['fn']) {
$duplicated = true;
q("delete from hook where id = %d",
intval($rv['id'])
);
logger('duplicate hook ' . $h[1] . ' removed');
}
}
}
if(! $duplicated) {
App::$hooks[$rv['hook']][] = [ $rv['file'], $rv['fn'], $rv['priority'], $rv['hook_version']];
}
}
}
//logger('hooks: ' . print_r(App::$hooks,true));
// logger('hooks: ' . print_r(App::$hooks,true));
}
/**
@@ -431,8 +455,28 @@ function insert_hook($hook, $fn, $version = 0, $priority = 0) {
*/
function call_hooks($name, &$data = null) {
$a = 0;
if((is_array(App::$hooks)) && (array_key_exists($name, App::$hooks))) {
if (isset(App::$hooks[$name])) {
foreach(App::$hooks[$name] as $hook) {
if ($name != 'permit_hook') { // avoid looping
$checkhook = [
'name'=>$name,
'hook'=>$hook,
'data'=>$data,
// Note: Since PHP uses COPY-ON-WRITE
// for variables, there is no cost to
// passing the $data structure (unless
// the permit_hook processors change the
// information it contains.
'permit'=>true
];
call_hooks('permit_hook',$checkhook);
if (!$checkhook['permit']) {
continue;
}
$data = $checkhook['data'];
}
$origfn = $hook[1];
if($hook[0])
@include_once($hook[0]);
@@ -958,9 +1002,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))
@@ -991,21 +1034,54 @@ 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"])) {
$root = \App::$override_markup_templates[$testroot][$s]["root"];
$s = \App::$override_markup_templates[$testroot][$s]["file"];
$template = $t->get_markup_template($s, $root);
} elseif (\App::$override_templateroot) {
$newroot = \App::$override_templateroot;
if ($newroot != '' && substr($newroot,-1) != '/' ) {
$newroot .= '/';
}
$newroot .= $root;
$template = $t->get_markup_template($s, $newroot);
} else {
$template = $t->get_markup_template($s, $root);
}
return $template;
}
}
/**

View File

@@ -370,7 +370,7 @@ function permissions_sql($owner_id, $remote_observer = null, $table = '') {
}
/**
* @brief Creates an addiontal SQL where statement to check permissions for an item.
* @brief Creates an additional SQL where statement to check permissions for an item.
*
* @param int $owner_id
* @param bool $remote_observer (optional) use current observer if unset
@@ -577,7 +577,7 @@ function init_groups_visitor($contact_id) {
// physical groups this channel is a member of
$r = q("SELECT hash FROM groups left join group_member on groups.id = group_member.gid WHERE xchan = '%s' ",
$r = q("SELECT hash FROM pgrp left join pgrp_member on pgrp.id = pgrp_member.gid WHERE xchan = '%s' ",
dbesc($contact_id)
);
if($r) {

View File

@@ -3,21 +3,32 @@
function contact_profile_assign($current) {
$o = '';
$o .= "<select id=\"contact-profile-selector\" name=\"profile_assign\" class=\"form-control\"/>\r\n";
$r = q("SELECT profile_guid, profile_name FROM profile WHERE uid = %d",
intval($_SESSION['uid']));
intval($_SESSION['uid'])
);
if($r) {
foreach($r as $rr) {
$selected = (($rr['profile_guid'] == $current) ? " selected=\"selected\" " : "");
$o .= "<option value=\"{$rr['profile_guid']}\" $selected >{$rr['profile_name']}</option>\r\n";
$options[$rr['profile_guid']] = $rr['profile_name'];
}
}
$o .= "</select>\r\n";
$select = [
'profile_assign',
t('Profile to assign new connections'),
$current,
'',
$options
];
$o = replace_macros(get_markup_template('field_select.tpl'),
[
'$field' => $select
]
);
return $o;
}
function contact_poll_interval($current, $disabled = false) {

View File

@@ -37,7 +37,13 @@ function replace_macros($s, $r) {
call_hooks('replace_macros', $arr);
$t = App::template_engine();
$output = $t->replace_macros($arr['template'], $arr['params']);
try {
$output = $t->replace_macros($arr['template'], $arr['params']);
} catch (Exception $e) {
logger("Unable to render template: ".$e->getMessage());
$output = "<h3>ERROR: there was an error creating the output.</h3>";
}
return $output;
}
@@ -2047,6 +2053,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])
@@ -2730,7 +2737,7 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $i
$grp = group_byname($profile_uid,$name);
if($grp) {
$g = q("select hash from groups where id = %d and visible = 1 limit 1",
$g = q("select hash from pgrp where id = %d and visible = 1 limit 1",
intval($grp)
);
if($g && $exclusive) {
@@ -2958,7 +2965,9 @@ function item_url_replace($channel,&$item,$old,$new,$oldnick = '') {
json_url_replace('/' . $oldnick . '/' ,'/' . $channel['channel_address'] . '/' ,$item['target']);
}
if(string_replace($old,$new,$item['body'])) {
$x = preg_replace("/".preg_quote($old,'/')."\/(search|\w+\/".$channel['channel_address'].")/", $new.'/${1}', $item['body']);
if($x) {
$item['body'] = $x;
$item['sig'] = base64url_encode(rsa_sign($item['body'],$channel['channel_prvkey']));
$item['item_verified'] = 1;
}
@@ -3251,17 +3260,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);
@@ -3412,3 +3421,41 @@ function get_forum_channels($uid) {
return $r;
}
function print_array($arr, $level = 0) {
$o = EMPTY_STR;
$tabs = EMPTY_STR;
if(is_array($arr)) {
for($x = 0; $x <= $level; $x ++) {
$tabs .= "\t";
}
$o .= '[' . "\n";
if(count($arr)) {
foreach($arr as $k => $v) {
if(is_array($v)) {
$o .= $tabs . '[' . $k . '] => ' . print_array($v, $level + 1) . "\n";
}
else {
$o .= $tabs . '[' . $k . '] => ' . print_val($v) . ",\n";
}
}
}
$o .= substr($tabs,0,-1) . ']' . (($level) ? ',' : ';' ). "\n";
return $o;
}
}
function print_val($v) {
if(is_bool($v)) {
if($v) return 'true';
return 'false';
}
if(is_string($v)) {
return "'" . $v . "'";
}
return $v;
}

View File

@@ -176,7 +176,7 @@ function xchan_change_key($oldx,$newx,$data) {
$tables = [
'abook' => 'abook_xchan',
'abconfig' => 'xchan',
'group_member' => 'xchan',
'pgrp_member' => 'xchan',
'chat' => 'chat_xchan',
'chatpresence' => 'cp_xchan',
'event' => 'event_xchan',

View File

@@ -12,6 +12,7 @@ require_once('include/crypto.php');
require_once('include/items.php');
require_once('include/queue_fn.php');
require_once('include/perm_upgrade.php');
require_once('include/msglib.php');
/**
@@ -491,7 +492,7 @@ function zot_refresh($them, $channel = null, $force = false) {
$profile_assign = get_pconfig($channel['channel_id'],'system','profile_assign','');
// Keep original perms to check if we need to notify them
$previous_perms = get_all_perms($channel['channel_id'],$x['hash']);
$previous_perms = get_all_perms($channel['channel_id'],$x['hash'],false);
$r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1",
dbesc($x['hash']),
@@ -560,7 +561,7 @@ function zot_refresh($them, $channel = null, $force = false) {
if($y) {
logger("New introduction received for {$channel['channel_name']}");
$new_perms = get_all_perms($channel['channel_id'],$x['hash']);
$new_perms = get_all_perms($channel['channel_id'],$x['hash'],false);
// Send a clone sync packet and a permissions update if permissions have changed
@@ -1118,6 +1119,7 @@ function zot_process_response($hub, $arr, $outq) {
}
foreach($x['delivery_report'] as $xx) {
call_hooks('dreport_process',$xx);
if(is_array($xx) && array_key_exists('message_id',$xx) && delivery_report_is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
@@ -1807,13 +1809,28 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $
else {
$arr['item_wall'] = 0;
}
if((! perm_is_allowed($channel['channel_id'],$sender['hash'],$perm)) && (! $tag_delivery) && (! $local_public)) {
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
$DR->update('permission denied');
$result[] = $DR->get();
continue;
}
if ((! $tag_delivery) && (! $local_public)) {
$allowed = (perm_is_allowed($channel['channel_id'],$sender['hash'],$perm));
if((! $allowed) && $perm == 'post_comments') {
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
if ($parent) {
$allowed = can_comment_on_post($d['hash'],$parent[0]);
}
}
if (! $allowed) {
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
$DR->update('permission denied');
$result[] = $DR->get();
continue;
}
}
if($arr['mid'] != $arr['parent_mid']) {
@@ -2315,16 +2332,13 @@ function process_mail_delivery($sender, $arr, $deliveries) {
}
$r = q("select id from mail where mid = '%s' and channel_id = %d limit 1",
$r = q("select id, conv_guid from mail where mid = '%s' and channel_id = %d limit 1",
dbesc($arr['mid']),
intval($channel['channel_id'])
);
if($r) {
if(intval($arr['mail_recalled'])) {
$x = q("delete from mail where id = %d and channel_id = %d",
intval($r[0]['id']),
intval($channel['channel_id'])
);
msg_drop($r[0]['id'], $channel['channel_id'], $r[0]['conv_guid']);
$DR->update('mail recalled');
$result[] = $DR->get();
logger('mail_recalled');
@@ -3306,13 +3320,13 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
}
if($groups_changed) {
$r = q("select hash as collection, visible, deleted, gname as name from groups where uid = %d",
$r = q("select hash as collection, visible, deleted, gname as name from pgrp where uid = %d",
intval($uid)
);
if($r)
$info['collections'] = $r;
$r = q("select groups.hash as collection, group_member.xchan as member from groups left join group_member on groups.id = group_member.gid where group_member.uid = %d",
$r = q("select pgrp.hash as collection, pgrp_member.xchan as member from pgrp left join pgrp_member on pgrp.id = pgrp_member.gid where pgrp_member.uid = %d",
intval($uid)
);
if($r)
@@ -3557,13 +3571,13 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
$disallowed = [
'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
'channel_system', 'channel_r_stream', 'channel_r_profile', 'channel_r_abook',
'channel_r_storage', 'channel_r_pages', 'channel_w_stream', 'channel_w_wall',
'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
'channel_a_delegate'
'channel_id', 'channel_account_id', 'channel_primary', 'channel_prvkey',
'channel_address', 'channel_notifyflags', 'channel_removed', 'channel_deleted',
'channel_system', 'channel_r_stream', 'channel_r_profile', 'channel_r_abook',
'channel_r_storage', 'channel_r_pages', 'channel_w_stream', 'channel_w_wall',
'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
'channel_a_delegate', 'channel_moved'
];
$clean = array();
@@ -3720,7 +3734,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
// sync collections (privacy groups) oh joy...
if(array_key_exists('collections',$arr) && is_array($arr['collections']) && count($arr['collections'])) {
$x = q("select * from groups where uid = %d",
$x = q("select * from pgrp where uid = %d",
intval($channel['channel_id'])
);
foreach($arr['collections'] as $cl) {
@@ -3736,7 +3750,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(($y['gname'] != $cl['name'])
|| ($y['visible'] != $cl['visible'])
|| ($y['deleted'] != $cl['deleted'])) {
q("update groups set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d",
q("update pgrp set gname = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d",
dbesc($cl['name']),
intval($cl['visible']),
intval($cl['deleted']),
@@ -3745,14 +3759,14 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
);
}
if(intval($cl['deleted']) && (! intval($y['deleted']))) {
q("delete from group_member where gid = %d",
q("delete from pgrp_member where gid = %d",
intval($y['id'])
);
}
}
}
if(! $found) {
$r = q("INSERT INTO groups ( hash, uid, visible, deleted, gname )
$r = q("INSERT INTO pgrp ( hash, uid, visible, deleted, gname )
VALUES( '%s', %d, %d, %d, '%s' ) ",
dbesc($cl['collection']),
intval($channel['channel_id']),
@@ -3776,10 +3790,10 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
}
if(! $found_local) {
q("delete from group_member where gid = %d",
q("delete from pgrp_member where gid = %d",
intval($y['id'])
);
q("update groups set deleted = 1 where id = %d and uid = %d",
q("update pgrp set deleted = 1 where id = %d and uid = %d",
intval($y['id']),
intval($channel['channel_id'])
);
@@ -3789,7 +3803,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
// reload the group list with any updates
$x = q("select * from groups where uid = %d",
$x = q("select * from pgrp where uid = %d",
intval($channel['channel_id'])
);
@@ -3816,7 +3830,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(isset($y['hash']) && isset($members[$y['hash']])) {
foreach($members[$y['hash']] as $member) {
$found = false;
$z = q("select xchan from group_member where gid = %d and uid = %d and xchan = '%s' limit 1",
$z = q("select xchan from pgrp_member where gid = %d and uid = %d and xchan = '%s' limit 1",
intval($y['id']),
intval($channel['channel_id']),
dbesc($member)
@@ -3827,7 +3841,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
// if somebody is in the group that wasn't before - add them
if(! $found) {
q("INSERT INTO group_member (uid, gid, xchan)
q("INSERT INTO pgrp_member (uid, gid, xchan)
VALUES( %d, %d, '%s' ) ",
intval($channel['channel_id']),
intval($y['id']),
@@ -3838,7 +3852,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
}
// now retrieve a list of members we have on this site
$m = q("select xchan from group_member where gid = %d and uid = %d",
$m = q("select xchan from pgrp_member where gid = %d and uid = %d",
intval($y['id']),
intval($channel['channel_id'])
);
@@ -3846,7 +3860,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
foreach($m as $mm) {
// if the local existing member isn't in the list we just received - remove them
if(! in_array($mm['xchan'],$members[$y['hash']])) {
q("delete from group_member where xchan = '%s' and gid = %d and uid = %d",
q("delete from pgrp_member where xchan = '%s' and gid = %d and uid = %d",
dbesc($mm['xchan']),
intval($y['id']),
intval($channel['channel_id'])
@@ -4419,7 +4433,7 @@ function zotinfo($arr) {
if(! $ret['follow_url'])
$ret['follow_url'] = z_root() . '/follow?f=&url=%s';
$permissions = get_all_perms($e['channel_id'],$ztarget_hash,false);
$permissions = get_all_perms($e['channel_id'],$ztarget_hash,false,false);
if($ztarget_hash) {
$permissions['connected'] = false;