Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev
This commit is contained in:
commit
06d2d31777
@ -2,21 +2,55 @@
|
||||
|
||||
namespace Zotlabs\Access;
|
||||
|
||||
|
||||
/**
|
||||
* @brief AccessList class.
|
||||
*
|
||||
* A class to hold an AccessList object with allowed and denied contacts and
|
||||
* groups.
|
||||
*/
|
||||
class AccessList {
|
||||
|
||||
/**
|
||||
* @brief Allow contacts
|
||||
* @var string
|
||||
*/
|
||||
private $allow_cid;
|
||||
/**
|
||||
* @brief Allow groups
|
||||
* @var string
|
||||
*/
|
||||
private $allow_gid;
|
||||
/**
|
||||
* @brief Deny contacts
|
||||
* @var string
|
||||
*/
|
||||
private $deny_cid;
|
||||
/**
|
||||
* @brief Deny groups
|
||||
* @var string
|
||||
*/
|
||||
private $deny_gid;
|
||||
/**
|
||||
* @brief Indicates if we are using the default constructor values or
|
||||
* values that have been set explicitly.
|
||||
* @var boolean
|
||||
*/
|
||||
private $explicit;
|
||||
|
||||
/* indicates if we are using the default constructor values or values that have been set explicitly. */
|
||||
|
||||
private $explicit;
|
||||
|
||||
/**
|
||||
* @brief Constructor for AccessList class.
|
||||
*
|
||||
* @note The array to pass to the constructor is different from the array
|
||||
* that you provide to the set() or set_from_array() functions.
|
||||
*
|
||||
* @param array $channel A channel array, where these entries are evaluated:
|
||||
* * \e string \b channel_allow_cid => string of allowed cids
|
||||
* * \e string \b channel_allow_gid => string of allowed gids
|
||||
* * \e string \b channel_deny_cid => string of denied cids
|
||||
* * \e string \b channel_deny_gid => string of denied gids
|
||||
*/
|
||||
function __construct($channel) {
|
||||
|
||||
if($channel) {
|
||||
if($channel) {
|
||||
$this->allow_cid = $channel['channel_allow_cid'];
|
||||
$this->allow_gid = $channel['channel_allow_gid'];
|
||||
$this->deny_cid = $channel['channel_deny_cid'];
|
||||
@ -32,61 +66,95 @@ class AccessList {
|
||||
$this->explicit = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get if we are using the default constructor values
|
||||
* or values that have been set explicitly.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function get_explicit() {
|
||||
return $this->explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AccessList from strings such as those in already
|
||||
* existing stored data items
|
||||
* @brief Set access list from strings such as those in already
|
||||
* existing stored data items.
|
||||
*
|
||||
* @note The array to pass to this set function is different from the array
|
||||
* that you provide to the constructor or set_from_array().
|
||||
*
|
||||
* @param array $arr
|
||||
* * \e string \b allow_cid => string of allowed cids
|
||||
* * \e string \b allow_gid => string of allowed gids
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
|
||||
function set($arr,$explicit = true) {
|
||||
function set($arr, $explicit = true) {
|
||||
$this->allow_cid = $arr['allow_cid'];
|
||||
$this->allow_gid = $arr['allow_gid'];
|
||||
$this->deny_cid = $arr['deny_cid'];
|
||||
$this->deny_gid = $arr['deny_gid'];
|
||||
|
||||
$this->explicit = $explicit;
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* return an array consisting of the current
|
||||
* access list components where the elements
|
||||
* are directly storable.
|
||||
* @brief Return an array consisting of the current access list components
|
||||
* where the elements are directly storable.
|
||||
*
|
||||
* @return Associative array with:
|
||||
* * \e string \b allow_cid => string of allowed cids
|
||||
* * \e string \b allow_gid => string of allowed gids
|
||||
* * \e string \b deny_cid => string of denied cids
|
||||
* * \e string \b deny_gid => string of denied gids
|
||||
*/
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
return [
|
||||
'allow_cid' => $this->allow_cid,
|
||||
'allow_gid' => $this->allow_gid,
|
||||
'deny_cid' => $this->deny_cid,
|
||||
'deny_gid' => $this->deny_gid,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AccessList from arrays, such as those provided by
|
||||
* acl_selector(). For convenience, a string (or non-array) input is
|
||||
* assumed to be a comma-separated list and auto-converted into an array.
|
||||
*/
|
||||
|
||||
function set_from_array($arr,$explicit = true) {
|
||||
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
|
||||
? $arr['contact_allow'] : explode(',',$arr['contact_allow']));
|
||||
* @brief Set access list components from arrays, such as those provided by
|
||||
* acl_selector().
|
||||
*
|
||||
* For convenience, a string (or non-array) input is assumed to be a
|
||||
* comma-separated list and auto-converted into an array.
|
||||
*
|
||||
* @note The array to pass to this set function is different from the array
|
||||
* that you provide to the constructor or set().
|
||||
*
|
||||
* @param array $arr An associative array with:
|
||||
* * \e array|string \b contact_allow => array with cids or comma-seperated string
|
||||
* * \e array|string \b group_allow => array with gids or comma-seperated string
|
||||
* * \e array|string \b contact_deny => array with cids or comma-seperated string
|
||||
* * \e array|string \b group_deny => array with gids or comma-seperated string
|
||||
* @param boolean $explicit (optional) default true
|
||||
*/
|
||||
function set_from_array($arr, $explicit = true) {
|
||||
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
|
||||
? $arr['contact_allow'] : explode(',', $arr['contact_allow']));
|
||||
$this->allow_gid = perms2str((is_array($arr['group_allow']))
|
||||
? $arr['group_allow'] : explode(',',$arr['group_allow']));
|
||||
? $arr['group_allow'] : explode(',', $arr['group_allow']));
|
||||
$this->deny_cid = perms2str((is_array($arr['contact_deny']))
|
||||
? $arr['contact_deny'] : explode(',',$arr['contact_deny']));
|
||||
? $arr['contact_deny'] : explode(',', $arr['contact_deny']));
|
||||
$this->deny_gid = perms2str((is_array($arr['group_deny']))
|
||||
? $arr['group_deny'] : explode(',',$arr['group_deny']));
|
||||
? $arr['group_deny'] : explode(',', $arr['group_deny']));
|
||||
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if any access lists component is set.
|
||||
*
|
||||
* @return boolean Return true if any of allow_* deny_* values is set.
|
||||
*/
|
||||
function is_private() {
|
||||
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -118,13 +118,29 @@ class Onepoll {
|
||||
|
||||
if($fetch_feed) {
|
||||
|
||||
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
|
||||
$feedurl .= '?f=&mindate=' . urlencode($last_update);
|
||||
if(strpos($contact['xchan_connurl'],z_root()) === 0) {
|
||||
// local channel - save a network fetch
|
||||
$c = channelx_by_hash($contact['xchan_hash']);
|
||||
if($c) {
|
||||
$x = [
|
||||
'success' => true,
|
||||
'body' => json_encode( [
|
||||
'success' => true,
|
||||
'messages' => zot_feed($c['channel_id'], $importer['xchan_hash'], [ 'mindate' => $last_update ])
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// remote fetch
|
||||
|
||||
$x = z_fetch_url($feedurl);
|
||||
$feedurl = str_replace('/poco/','/zotfeed/',$contact['xchan_connurl']);
|
||||
$feedurl .= '?f=&mindate=' . urlencode($last_update) . '&zid=' . $importer['channel_address'] . '@' . \App::get_hostname();
|
||||
$recurse = 0;
|
||||
$x = z_fetch_url($feedurl, false, $recurse, [ 'session' => true ]);
|
||||
}
|
||||
|
||||
logger('feed_update: ' . print_r($x,true), LOGGER_DATA);
|
||||
|
||||
}
|
||||
|
||||
if(($x) && ($x['success'])) {
|
||||
|
@ -178,6 +178,25 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
'$header' => t('Messages'),
|
||||
));
|
||||
|
||||
if(argc() == 3 && intval(argv(1)) && argv(2) === 'download') {
|
||||
|
||||
$r = q("select * from mail where id = %d and channel_id = %d",
|
||||
intval(argv(1)),
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
if($r) {
|
||||
|
||||
header('Content-type: ' . $r[0]['mail_mimetype']);
|
||||
header('Content-disposition: attachment; filename="' . t('message') . '-' . $r[0]['id'] . '"' );
|
||||
$body = (($r[0]['mail_obscured']) ? base64url_decode(str_rot47($r[0]['body'])) : $r[0]['body']);
|
||||
echo $body;
|
||||
killme();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if((argc() == 4) && (argv(2) === 'drop')) {
|
||||
if(! intval(argv(3)))
|
||||
return;
|
||||
@ -370,6 +389,11 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
foreach($messages as $message) {
|
||||
|
||||
$s = theme_attachments($message);
|
||||
|
||||
if($message['mail_raw'])
|
||||
$message['body'] = mail_prepare_binary([ 'id' => $message['id'] ]);
|
||||
else
|
||||
$message['body'] = zidify_links(smilies(bbcode($message['body'])));
|
||||
|
||||
$mails[] = array(
|
||||
'mailbox' => $mailbox,
|
||||
@ -382,7 +406,7 @@ class Mail extends \Zotlabs\Web\Controller {
|
||||
'to_url' => chanlink_hash($message['to_xchan']),
|
||||
'to_photo' => $message['to']['xchan_photo_s'],
|
||||
'subject' => $message['title'],
|
||||
'body' => zidify_links(smilies(bbcode($message['body']))),
|
||||
'body' => $message['body'],
|
||||
'attachments' => $s,
|
||||
'delete' => t('Delete message'),
|
||||
'dreport' => t('Delivery report'),
|
||||
|
@ -508,6 +508,7 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$this->check_add($ck_funcs, t('PDO database PHP module'), true, true);
|
||||
$this->check_add($ck_funcs, t('mb_string PHP module'), true, true);
|
||||
$this->check_add($ck_funcs, t('xml PHP module'), true, true);
|
||||
$this->check_add($ck_funcs, t('zip PHP module'), true, true);
|
||||
|
||||
if(function_exists('apache_get_modules')){
|
||||
if (! in_array('mod_rewrite', apache_get_modules())) {
|
||||
@ -550,8 +551,12 @@ class Setup extends \Zotlabs\Web\Controller {
|
||||
$ck_funcs[4]['help'] = t('Error: mb_string PHP module required but not installed.');
|
||||
}
|
||||
if(! extension_loaded('xml')) {
|
||||
$ck_funcs[5]['status'] = false;
|
||||
$ck_funcs[5]['help'] = t('Error: xml PHP module required for DAV but not installed.');
|
||||
}
|
||||
if(! extension_loaded('zip')) {
|
||||
$ck_funcs[6]['status'] = false;
|
||||
$ck_funcs[6]['help'] = t('Error: xml PHP module required for DAV but not installed.');
|
||||
$ck_funcs[6]['help'] = t('Error: zip PHP module required but not installed.');
|
||||
}
|
||||
|
||||
$checks = array_merge($checks, $ck_funcs);
|
||||
|
@ -22,7 +22,8 @@ class Zotfeed extends \Zotlabs\Web\Controller {
|
||||
|
||||
$observer = \App::get_observer();
|
||||
|
||||
|
||||
logger('observer: ' . get_observer_hash(), LOGGER_DEBUG);
|
||||
|
||||
$channel_address = ((argc() > 1) ? argv(1) : '');
|
||||
if($channel_address) {
|
||||
$r = q("select channel_id, channel_name from channel where channel_address = '%s' and channel_removed = 0 limit 1",
|
||||
|
2
boot.php
2
boot.php
@ -49,7 +49,7 @@ require_once('include/hubloc.php');
|
||||
|
||||
|
||||
define ( 'PLATFORM_NAME', 'hubzilla' );
|
||||
define ( 'STD_VERSION', '2.3.4' );
|
||||
define ( 'STD_VERSION', '2.3.5' );
|
||||
define ( 'ZOT_REVISION', '1.2' );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1190 );
|
||||
|
@ -3003,8 +3003,14 @@ function mail_store($arr) {
|
||||
$arr['body'] = escape_tags($arr['body']);
|
||||
}
|
||||
|
||||
if(array_key_exists('attach',$arr) && is_array($arr['attach']))
|
||||
$arr['attach'] = json_encode($arr['attach']);
|
||||
if(array_key_exists('attach',$arr)) {
|
||||
if(is_array($arr['attach'])) {
|
||||
$arr['attach'] = json_encode($arr['attach']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$arr['attach'] = '';
|
||||
}
|
||||
|
||||
$arr['account_id'] = ((x($arr,'account_id')) ? intval($arr['account_id']) : 0);
|
||||
$arr['mid'] = ((x($arr,'mid')) ? notags(trim($arr['mid'])) : random_string());
|
||||
@ -3015,6 +3021,7 @@ function mail_store($arr) {
|
||||
$arr['title'] = ((x($arr,'title')) ? trim($arr['title']) : '');
|
||||
$arr['parent_mid'] = ((x($arr,'parent_mid')) ? notags(trim($arr['parent_mid'])) : '');
|
||||
$arr['body'] = ((x($arr,'body')) ? trim($arr['body']) : '');
|
||||
$arr['sig'] = ((x($arr,'sig')) ? trim($arr['sig']) : '');
|
||||
$arr['conv_guid'] = ((x($arr,'conv_guid')) ? trim($arr['conv_guid']) : '');
|
||||
|
||||
$arr['mail_flags'] = ((x($arr,'mail_flags')) ? intval($arr['mail_flags']) : 0 );
|
||||
|
@ -35,13 +35,15 @@ function send_message($uid = 0, $recipient = '', $body = '', $subject = '', $rep
|
||||
$body = cleanup_bbcode($body);
|
||||
$results = linkify_tags($a, $body, $uid);
|
||||
|
||||
|
||||
if(preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$match))
|
||||
$attaches = $match[1];
|
||||
if(! $raw) {
|
||||
if(preg_match_all("/\[attachment\](.*?)\[\/attachment\]/",((strpos($body,'[/crypt]')) ? $_POST['media_str'] : $body),$match)) {
|
||||
$attaches = $match[1];
|
||||
}
|
||||
}
|
||||
|
||||
$attachments = '';
|
||||
|
||||
if(preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
|
||||
if((! $raw) && preg_match_all('/(\[attachment\](.*?)\[\/attachment\])/',$body,$match)) {
|
||||
$attachments = array();
|
||||
foreach($match[2] as $mtch) {
|
||||
$hash = substr($mtch,0,strpos($mtch,','));
|
||||
@ -184,7 +186,7 @@ function send_message($uid = 0, $recipient = '', $body = '', $subject = '', $rep
|
||||
|
||||
if($subject)
|
||||
$subject = str_rot47(base64url_encode($subject));
|
||||
if($body)
|
||||
if(($body )&& (! $raw))
|
||||
$body = str_rot47(base64url_encode($body));
|
||||
|
||||
$sig = ''; // placeholder
|
||||
@ -514,6 +516,9 @@ function private_messages_fetch_conversation($channel_id, $messageitem_id, $upda
|
||||
if($messages[$k]['body'])
|
||||
$messages[$k]['body'] = base64url_decode(str_rot47($messages[$k]['body']));
|
||||
}
|
||||
if($messages[$k]['mail_raw'])
|
||||
$messages[$k]['body'] = mail_prepare_binary([ 'id' => $messages[$k]['id'] ]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
173
include/nav.php
173
include/nav.php
@ -2,6 +2,10 @@
|
||||
|
||||
use \Zotlabs\Lib as Zlib;
|
||||
|
||||
require_once('include/security.php');
|
||||
require_once('include/menu.php');
|
||||
|
||||
|
||||
function nav() {
|
||||
|
||||
/**
|
||||
@ -38,8 +42,8 @@ EOT;
|
||||
$observer = App::get_observer();
|
||||
|
||||
require_once('include/conversation.php');
|
||||
$is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false);
|
||||
$navapps[] = profile_tabs($a, $is_owner, \App::$profile['channel_address']);
|
||||
$is_owner = (((local_channel()) && (App::$profile['profile_uid'] == local_channel())) ? true : false);
|
||||
$navapps[] = channel_apps($is_owner, App::$profile['channel_address']);
|
||||
|
||||
$myident = (($channel) ? $channel['xchan_addr'] : '');
|
||||
|
||||
@ -312,3 +316,168 @@ function nav_set_selected($item){
|
||||
);
|
||||
App::$nav_sel[$item] = 'active';
|
||||
}
|
||||
|
||||
|
||||
|
||||
function channel_apps($is_owner = false, $nickname = null) {
|
||||
|
||||
// Don't provide any channel apps if we're running as the sys channel
|
||||
|
||||
if(App::$is_sys)
|
||||
return '';
|
||||
|
||||
if(! get_pconfig($uid, 'system', 'channelapps','1'))
|
||||
return '';
|
||||
|
||||
$channel = App::get_channel();
|
||||
|
||||
if($channel && 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;
|
||||
}
|
||||
else {
|
||||
$cal_link = '/cal/' . $nickname;
|
||||
}
|
||||
|
||||
$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 = [
|
||||
[
|
||||
'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[] = [
|
||||
'label' => t('About'),
|
||||
'url' => $pr,
|
||||
'sel' => ((argv(0) == 'profile') ? 'active' : ''),
|
||||
'title' => t('Profile Details'),
|
||||
'id' => 'profile-tab',
|
||||
'icon' => 'user'
|
||||
];
|
||||
}
|
||||
if ($p['view_storage']) {
|
||||
$tabs[] = [
|
||||
'label' => t('Photos'),
|
||||
'url' => z_root() . '/photos/' . $nickname,
|
||||
'sel' => ((argv(0) == 'photos') ? 'active' : ''),
|
||||
'title' => t('Photo Albums'),
|
||||
'id' => 'photo-tab',
|
||||
'icon' => 'photo'
|
||||
];
|
||||
$tabs[] = [
|
||||
'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[] = [
|
||||
'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 = ZLib\Chatroom::list_count($uid);
|
||||
if ($has_chats) {
|
||||
$tabs[] = [
|
||||
'label' => t('Chatrooms'),
|
||||
'url' => z_root() . '/chat/' . $nickname,
|
||||
'sel' => ((argv(0) == 'chat') ? 'active' : '' ),
|
||||
'title' => t('Chatrooms'),
|
||||
'id' => 'chat-tab',
|
||||
'icon' => 'comments-o'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
|
||||
if ($is_owner && $has_bookmarks) {
|
||||
$tabs[] = [
|
||||
'label' => t('Bookmarks'),
|
||||
'url' => z_root() . '/bookmarks',
|
||||
'sel' => ((argv(0) == 'bookmarks') ? 'active' : ''),
|
||||
'title' => t('Saved Bookmarks'),
|
||||
'id' => 'bookmarks-tab',
|
||||
'icon' => 'bookmark'
|
||||
];
|
||||
}
|
||||
|
||||
if($has_webpages && feature_enabled($uid,'webpages')) {
|
||||
$tabs[] = [
|
||||
'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[] = [
|
||||
'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'),
|
||||
[
|
||||
'$tabs' => $arr['tabs'],
|
||||
'$name' => App::$profile['channel_name'],
|
||||
'$thumb' => App::$profile['thumb']
|
||||
]
|
||||
);
|
||||
}
|
@ -597,18 +597,24 @@ function stream_perms_api_uids($perms = NULL, $limit = 0, $rand = 0 ) {
|
||||
$random_sql = (($rand) ? " ORDER BY " . db_getfunc('RAND') . " " : '');
|
||||
if(local_channel())
|
||||
$ret[] = local_channel();
|
||||
$x = q("select uid from pconfig where cat = 'perm_limits' and k = 'view_stream' and ( v & %d ) > 0 ",
|
||||
intval($perms)
|
||||
);
|
||||
$x = q("select uid, v from pconfig where cat = 'perm_limits' and k = 'view_stream' ");
|
||||
if($x) {
|
||||
$ids = ids_to_querystr($x,'uid');
|
||||
$r = q("select channel_id from channel where channel_id in ( $ids ) and ( channel_pageflags & %d ) = 0 and channel_system = 0 and channel_removed = 0 $random_sql $limit_sql ",
|
||||
intval(PAGE_ADULT|PAGE_CENSORED)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
if(! in_array($rr['channel_id'], $ret))
|
||||
$ret[] = $rr['channel_id'];
|
||||
$y = [];
|
||||
foreach($x as $xv) {
|
||||
if(intval($xv['v']) & $perms) {
|
||||
$y[] = $xv;
|
||||
}
|
||||
}
|
||||
if($y) {
|
||||
$ids = ids_to_querystr($y,'uid');
|
||||
$r = q("select channel_id from channel where channel_id in ( $ids ) and ( channel_pageflags & %d ) = 0 and channel_system = 0 and channel_removed = 0 $random_sql $limit_sql ",
|
||||
intval(PAGE_ADULT|PAGE_CENSORED)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
if(! in_array($rr['channel_id'], $ret))
|
||||
$ret[] = $rr['channel_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -635,19 +641,25 @@ function stream_perms_xchans($perms = NULL ) {
|
||||
if(local_channel())
|
||||
$ret[] = get_observer_hash();
|
||||
|
||||
$x = q("select uid from pconfig where cat = 'perm_limits' and k = 'view_stream' and ( v & %d ) > 0 ",
|
||||
intval($perms)
|
||||
);
|
||||
$x = q("select uid from pconfig where cat = 'perm_limits' and k = 'view_stream' ");
|
||||
if($x) {
|
||||
$ids = ids_to_querystr($x,'uid');
|
||||
$r = q("select channel_hash from channel where channel_id in ( $ids ) and ( channel_pageflags & %d ) = 0 and channel_system = 0 and channel_removed = 0 ",
|
||||
intval(PAGE_ADULT|PAGE_CENSORED)
|
||||
);
|
||||
$y = [];
|
||||
foreach($x as $xv) {
|
||||
if(intval($xv['v']) & $perms) {
|
||||
$y[] = $xv;
|
||||
}
|
||||
}
|
||||
if($y) {
|
||||
$ids = ids_to_querystr($y,'uid');
|
||||
$r = q("select channel_hash from channel where channel_id in ( $ids ) and ( channel_pageflags & %d ) = 0 and channel_system = 0 and channel_removed = 0 ",
|
||||
intval(PAGE_ADULT|PAGE_CENSORED)
|
||||
);
|
||||
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
if(! in_array($rr['channel_hash'], $ret))
|
||||
$ret[] = $rr['channel_hash'];
|
||||
if($r) {
|
||||
foreach($r as $rr)
|
||||
if(! in_array($rr['channel_hash'], $ret))
|
||||
$ret[] = $rr['channel_hash'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$str = '';
|
||||
|
@ -110,7 +110,7 @@ technical abilities.
|
||||
php.ini file - and with no hosting provider restrictions on the use of
|
||||
exec() and proc_open().
|
||||
|
||||
- curl, gd (with at least jpeg and png support), mysqli, mbstring, xml,
|
||||
- curl, gd (with at least jpeg and png support), mysqli, mbstring, xml, zip
|
||||
and openssl extensions. The imagick extension MAY be used instead of gd,
|
||||
but is not required and MAY also be disabled via configuration option.
|
||||
|
||||
|
1
library/bootstrap/css/bootstrap.css
vendored
1
library/bootstrap/css/bootstrap.css
vendored
@ -4078,6 +4078,7 @@ tbody.collapse.show {
|
||||
|
||||
.card-title {
|
||||
margin-bottom: 0.75rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.card-subtitle {
|
||||
|
File diff suppressed because one or more lines are too long
2
library/bootstrap/css/bootstrap.min.css
vendored
2
library/bootstrap/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
53
library/bootstrap/js/bootstrap.js
vendored
53
library/bootstrap/js/bootstrap.js
vendored
@ -8,16 +8,14 @@ if (typeof jQuery === 'undefined') {
|
||||
throw new Error('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.')
|
||||
}
|
||||
|
||||
+function ($) {
|
||||
(function ($) {
|
||||
var version = $.fn.jquery.split(' ')[0].split('.')
|
||||
if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {
|
||||
throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
|
||||
}
|
||||
}(jQuery);
|
||||
|
||||
|
||||
+function () {
|
||||
})(jQuery);
|
||||
|
||||
(function () {
|
||||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
@ -551,6 +549,7 @@ var Carousel = function ($) {
|
||||
var TRANSITION_DURATION = 600;
|
||||
var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
|
||||
var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
|
||||
var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
|
||||
|
||||
var Default = {
|
||||
interval: 5000,
|
||||
@ -581,6 +580,7 @@ var Carousel = function ($) {
|
||||
KEYDOWN: 'keydown' + EVENT_KEY,
|
||||
MOUSEENTER: 'mouseenter' + EVENT_KEY,
|
||||
MOUSELEAVE: 'mouseleave' + EVENT_KEY,
|
||||
TOUCHEND: 'touchend' + EVENT_KEY,
|
||||
LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY,
|
||||
CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
|
||||
};
|
||||
@ -623,6 +623,8 @@ var Carousel = function ($) {
|
||||
this._isPaused = false;
|
||||
this._isSliding = false;
|
||||
|
||||
this.touchTimeout = null;
|
||||
|
||||
this._config = this._getConfig(config);
|
||||
this._element = $(element)[0];
|
||||
this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];
|
||||
@ -742,12 +744,30 @@ var Carousel = function ($) {
|
||||
});
|
||||
}
|
||||
|
||||
if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) {
|
||||
if (this._config.pause === 'hover') {
|
||||
$(this._element).on(Event.MOUSEENTER, function (event) {
|
||||
return _this4.pause(event);
|
||||
}).on(Event.MOUSELEAVE, function (event) {
|
||||
return _this4.cycle(event);
|
||||
});
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
// if it's a touch-enabled device, mouseenter/leave are fired as
|
||||
// part of the mouse compatibility events on first tap - the carousel
|
||||
// would stop cycling until user tapped out of it;
|
||||
// here, we listen for touchend, explicitly pause the carousel
|
||||
// (as if it's the second time we tap on it, mouseenter compat event
|
||||
// is NOT fired) and after a timeout (to allow for mouse compatibility
|
||||
// events to fire) we explicitly restart cycling
|
||||
$(this._element).on(Event.TOUCHEND, function () {
|
||||
_this4.pause();
|
||||
if (_this4.touchTimeout) {
|
||||
clearTimeout(_this4.touchTimeout);
|
||||
}
|
||||
_this4.touchTimeout = setTimeout(function (event) {
|
||||
return _this4.cycle(event);
|
||||
}, TOUCHEVENT_COMPAT_WAIT + _this4._config.interval);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1463,7 +1483,7 @@ var Dropdown = function ($) {
|
||||
// only needed because of broken event delegation on iOS
|
||||
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
||||
if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
|
||||
$('body').children().on('mouseover', '*', $.noop);
|
||||
$('body').children().on('mouseover', null, $.noop);
|
||||
}
|
||||
|
||||
this.focus();
|
||||
@ -1537,7 +1557,7 @@ var Dropdown = function ($) {
|
||||
// if this is a touch-enabled device we remove the extra
|
||||
// empty mouseover listeners we added for iOS support
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().off('mouseover', '*', $.noop);
|
||||
$('body').children().off('mouseover', null, $.noop);
|
||||
}
|
||||
|
||||
toggles[i].setAttribute('aria-expanded', 'false');
|
||||
@ -3041,6 +3061,14 @@ var Tooltip = function ($) {
|
||||
|
||||
$(tip).addClass(ClassName.SHOW);
|
||||
|
||||
// if this is a touch-enabled device we add extra
|
||||
// empty mouseover listeners to the body's immediate children;
|
||||
// only needed because of broken event delegation on iOS
|
||||
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().on('mouseover', null, $.noop);
|
||||
}
|
||||
|
||||
var complete = function complete() {
|
||||
var prevHoverState = _this23._hoverState;
|
||||
_this23._hoverState = null;
|
||||
@ -3089,6 +3117,12 @@ var Tooltip = function ($) {
|
||||
|
||||
$(tip).removeClass(ClassName.SHOW);
|
||||
|
||||
// if this is a touch-enabled device we remove the extra
|
||||
// empty mouseover listeners we added for iOS support
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$('body').children().off('mouseover', null, $.noop);
|
||||
}
|
||||
|
||||
this._activeTrigger[Trigger.CLICK] = false;
|
||||
this._activeTrigger[Trigger.FOCUS] = false;
|
||||
this._activeTrigger[Trigger.HOVER] = false;
|
||||
@ -3593,4 +3627,5 @@ var Popover = function ($) {
|
||||
return Popover;
|
||||
}(jQuery);
|
||||
|
||||
}();
|
||||
|
||||
})()
|
4
library/bootstrap/js/bootstrap.min.js
vendored
4
library/bootstrap/js/bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
189
tests/unit/Access/AccessListTest.php
Normal file
189
tests/unit/Access/AccessListTest.php
Normal file
@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2017 Hubzilla
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Zotlabs\Tests\Unit\Access;
|
||||
|
||||
use Zotlabs\Tests\Unit\UnitTestCase;
|
||||
use Zotlabs\Access\AccessList;
|
||||
|
||||
/**
|
||||
* @brief Unit Test case for AccessList class.
|
||||
*
|
||||
* @covers Zotlabs\Access\AccessList
|
||||
*/
|
||||
class AccessListTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @brief Expected result for most tests.
|
||||
* @var array
|
||||
*/
|
||||
protected $expectedResult = [
|
||||
'allow_cid' => '<acid><acid2>',
|
||||
'allow_gid' => '<agid>',
|
||||
'deny_cid' => '',
|
||||
'deny_gid' => '<dgid><dgid2>'
|
||||
];
|
||||
|
||||
|
||||
|
||||
public function testConstructor() {
|
||||
$channel = [
|
||||
'channel_allow_cid' => '<acid><acid2>',
|
||||
'channel_allow_gid' => '<agid>',
|
||||
'channel_deny_cid' => '',
|
||||
'channel_deny_gid' => '<dgid><dgid2>'
|
||||
];
|
||||
|
||||
$accessList = new AccessList($channel);
|
||||
|
||||
$this->assertEquals($this->expectedResult, $accessList->get());
|
||||
$this->assertFalse($accessList->get_explicit());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException PHPUnit\Framework\Error\Error
|
||||
*/
|
||||
public function testPHPErrorOnInvalidConstructor() {
|
||||
$accessList = new AccessList('invalid');
|
||||
// Causes: "Illegal string offset 'channel_allow_cid'"
|
||||
}
|
||||
|
||||
public function testDefaultGetExplicit() {
|
||||
$accessList = new AccessList([]);
|
||||
|
||||
$this->assertFalse($accessList->get_explicit());
|
||||
}
|
||||
|
||||
public function testDefaultGet() {
|
||||
$arr = [
|
||||
'allow_cid' => '',
|
||||
'allow_gid' => '',
|
||||
'deny_cid' => '',
|
||||
'deny_gid' => ''
|
||||
];
|
||||
|
||||
$accessList = new AccessList([]);
|
||||
|
||||
$this->assertEquals($arr, $accessList->get());
|
||||
}
|
||||
|
||||
public function testSet() {
|
||||
$arr = [
|
||||
'allow_cid' => '<acid><acid2>',
|
||||
'allow_gid' => '<agid>',
|
||||
'deny_cid' => '',
|
||||
'deny_gid' => '<dgid><dgid2>'
|
||||
];
|
||||
$accessList = new AccessList([]);
|
||||
|
||||
// default explicit true
|
||||
$accessList->set($arr);
|
||||
|
||||
$this->assertEquals($this->expectedResult, $accessList->get());
|
||||
$this->assertTrue($accessList->get_explicit());
|
||||
|
||||
// set explicit false
|
||||
$accessList->set($arr, false);
|
||||
|
||||
$this->assertEquals($this->expectedResult, $accessList->get());
|
||||
$this->assertFalse($accessList->get_explicit());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException PHPUnit\Framework\Error\Error
|
||||
*/
|
||||
public function testPHPErrorOnInvalidSet() {
|
||||
$accessList = new AccessList([]);
|
||||
|
||||
$accessList->set('invalid');
|
||||
// Causes: "Illegal string offset 'allow_cid'"
|
||||
}
|
||||
|
||||
/**
|
||||
* set_from_array() calls some other functions, too which are not yet unit tested.
|
||||
* @uses ::perms2str()
|
||||
*/
|
||||
public function testSetFromArray() {
|
||||
// array
|
||||
$arraySetFromArray = [
|
||||
'contact_allow' => ['acid', 'acid2'],
|
||||
'group_allow' => ['agid'],
|
||||
'contact_deny' => [],
|
||||
'group_deny' => ['dgid', 'dgid2']
|
||||
];
|
||||
$accessList = new AccessList([]);
|
||||
$accessList->set_from_array($arraySetFromArray);
|
||||
|
||||
$this->assertEquals($this->expectedResult, $accessList->get());
|
||||
$this->assertTrue($accessList->get_explicit());
|
||||
|
||||
|
||||
// string
|
||||
$stringSetFromArray = [
|
||||
'contact_allow' => 'acid,acid2',
|
||||
'group_allow' => 'agid',
|
||||
'contact_deny' => '',
|
||||
'group_deny' => 'dgid, dgid2'
|
||||
];
|
||||
$accessList2 = new AccessList([]);
|
||||
$accessList2->set_from_array($stringSetFromArray, false);
|
||||
|
||||
$this->assertEquals($this->expectedResult, $accessList2->get());
|
||||
$this->assertFalse($accessList2->get_explicit());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider isprivateProvider
|
||||
*/
|
||||
public function testIsPrivate($channel) {
|
||||
$accessListPublic = new AccessList([]);
|
||||
$this->assertFalse($accessListPublic->is_private());
|
||||
|
||||
$accessListPrivate = new AccessList($channel);
|
||||
$this->assertTrue($accessListPrivate->is_private());
|
||||
}
|
||||
|
||||
public function isprivateProvider() {
|
||||
return [
|
||||
'all set' => [[
|
||||
'channel_allow_cid' => '<acid>',
|
||||
'channel_allow_gid' => '<agid>',
|
||||
'channel_deny_cid' => '<dcid>',
|
||||
'channel_deny_gid' => '<dgid>'
|
||||
]],
|
||||
'only one set' => [[
|
||||
'channel_allow_cid' => '<acid>',
|
||||
'channel_allow_gid' => '',
|
||||
'channel_deny_cid' => '',
|
||||
'channel_deny_gid' => ''
|
||||
]],
|
||||
'acid+null' => [[
|
||||
'channel_allow_cid' => '<acid>',
|
||||
'channel_allow_gid' => null,
|
||||
'channel_deny_cid' => '',
|
||||
'channel_deny_gid' => ''
|
||||
]]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -29,6 +29,8 @@ use Zotlabs\Lib\PermissionDescription;
|
||||
|
||||
/**
|
||||
* @brief Unit Test case for PermissionDescription class.
|
||||
*
|
||||
* @covers Zotlabs\Lib\PermissionDescription
|
||||
*/
|
||||
class PermissionDescriptionTest extends UnitTestCase {
|
||||
|
||||
|
1109
util/hmessages.po
1109
util/hmessages.po
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user