Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge

This commit is contained in:
zotlabs 2018-01-12 01:26:01 -08:00
commit e8958b1fb8
37 changed files with 414 additions and 170 deletions

View File

@ -3,10 +3,14 @@
namespace Zotlabs\Access; namespace Zotlabs\Access;
/** /**
* @brief AccessList class. * @brief AccessList class which represents individual content ACLs.
* *
* A class to hold an AccessList object with allowed and denied contacts and * A class to hold an AccessList object with allowed and denied contacts and
* groups. * groups.
*
* After evaluating @ref ::Zotlabs::Access::PermissionLimits "PermissionLimits"
* and @ref ::Zotlabs::Lib::Permcat "Permcat"s individual content ACLs are evaluated.
* These answer the question "Can Joe view *this* album/photo?".
*/ */
class AccessList { class AccessList {
/** /**
@ -103,7 +107,7 @@ class AccessList {
* @brief Return an array consisting of the current access list components * @brief Return an array consisting of the current access list components
* where the elements are directly storable. * where the elements are directly storable.
* *
* @return Associative array with: * @return array An associative array with:
* * \e string \b allow_cid => string of allowed cids * * \e string \b allow_cid => string of allowed cids
* * \e string \b allow_gid => string of allowed gids * * \e string \b allow_gid => string of allowed gids
* * \e string \b deny_cid => string of denied cids * * \e string \b deny_cid => string of denied cids

View File

@ -2,35 +2,90 @@
namespace Zotlabs\Access; namespace Zotlabs\Access;
use \Zotlabs\Lib as ZLib; use Zotlabs\Lib\PConfig;
/**
* @brief Permission limits.
*
* Permission limits are a very high level permission setting. They are hard
* limits by design.
* "Who can view my photos (at all)?"
* "Who can post photos in my albums (at all)?"
*
* For viewing permissions we generally set these to 'anybody' and for write
* permissions we generally set them to 'those I allow', though many people
* restrict the viewing permissions further for things like 'Can view my connections'.
*
* People get confused enough by permissions that we wanted a place to set their
* privacy expectations once and be done with it.
*
* Connection related permissions like "Can Joe view my photos?" are handled by
* @ref ::Zotlabs::Lib::Permcat "Permcat" and inherit from the channel's Permission
* limits.
*
* @see Permissions
*/
class PermissionLimits { class PermissionLimits {
/**
* @brief Get standard permission limits.
*
* Viewing permissions and post_comments permission are set to 'anybody',
* other permissions are set to 'those I allow'.
*
* The list of permissions comes from Permissions::Perms().
*
* @return array
*/
static public function Std_Limits() { static public function Std_Limits() {
$limits = [];
$perms = Permissions::Perms(); $perms = Permissions::Perms();
$limits = array();
foreach($perms as $k => $v) { foreach($perms as $k => $v) {
if(strstr($k,'view') || $k === 'post_comments') if(strstr($k, 'view') || $k === 'post_comments')
$limits[$k] = PERMS_PUBLIC; $limits[$k] = PERMS_PUBLIC;
else else
$limits[$k] = PERMS_SPECIFIC; $limits[$k] = PERMS_SPECIFIC;
} }
return $limits; return $limits;
} }
static public function Set($channel_id,$perm,$perm_limit) { /**
ZLib\PConfig::Set($channel_id,'perm_limits',$perm,$perm_limit); * @brief Sets a permission limit for a channel.
*
* @param int $channel_id
* @param string $perm
* @param int $perm_limit one of PERMS_* constants
*/
static public function Set($channel_id, $perm, $perm_limit) {
PConfig::Set($channel_id, 'perm_limits', $perm, $perm_limit);
} }
static public function Get($channel_id,$perm = '') { /**
* @brief Get a channel's permission limits.
*
* Return a channel's permission limits from PConfig. If $perm is set just
* return this permission limit, if not set, return an array with all
* permission limits.
*
* @param int $channel_id
* @param string $perm (optional)
* @return
* * \b boolean false if no perm_limits set for this channel
* * \b int if $perm is set, return one of PERMS_* constants for this permission
* * \b array with all permission limits, if $perm is not set
*/
static public function Get($channel_id, $perm = '') {
if($perm) { if($perm) {
return Zlib\PConfig::Get($channel_id,'perm_limits',$perm); return PConfig::Get($channel_id, 'perm_limits', $perm);
}
else {
Zlib\PConfig::Load($channel_id);
if(array_key_exists($channel_id,\App::$config) && array_key_exists('perm_limits',\App::$config[$channel_id]))
return \App::$config[$channel_id]['perm_limits'];
return false;
} }
PConfig::Load($channel_id);
if(array_key_exists($channel_id, \App::$config)
&& array_key_exists('perm_limits', \App::$config[$channel_id]))
return \App::$config[$channel_id]['perm_limits'];
return false;
} }
} }

View File

@ -114,8 +114,9 @@ function getRemoteFileSize($url)
return strlen($data); return strlen($data);
}); });
$result = curl_exec($ch); curl_exec($ch);
$info = curl_getinfo($ch); curl_getinfo($ch);
curl_close($ch);
return $size; return $size;
} }

View File

@ -3,11 +3,13 @@
namespace Zotlabs\Lib; namespace Zotlabs\Lib;
/** /**
* MarkdownSoap * @brief MarkdownSoap class.
*
* Purify Markdown for storage * Purify Markdown for storage
* @code{.php}
* $x = new MarkdownSoap($string_to_be_cleansed); * $x = new MarkdownSoap($string_to_be_cleansed);
* $text = $x->clean(); * $text = $x->clean();
* * @endcode
* What this does: * What this does:
* 1. extracts code blocks and privately escapes them from processing * 1. extracts code blocks and privately escapes them from processing
* 2. Run html purifier on the content * 2. Run html purifier on the content
@ -15,24 +17,28 @@ namespace Zotlabs\Lib;
* 4. run htmlspecialchars on the entire content for safe storage * 4. run htmlspecialchars on the entire content for safe storage
* *
* At render time: * At render time:
* @code{.php}
* $markdown = \Zotlabs\Lib\MarkdownSoap::unescape($text); * $markdown = \Zotlabs\Lib\MarkdownSoap::unescape($text);
* $html = \Michelf\MarkdownExtra::DefaultTransform($markdown); * $html = \Michelf\MarkdownExtra::DefaultTransform($markdown);
* @endcode
*/ */
class MarkdownSoap { class MarkdownSoap {
/**
* @var string
*/
private $str;
/**
* @var string
*/
private $token; private $token;
private $str;
function __construct($s) { function __construct($s) {
$this->str = $s; $this->str = $s;
$this->token = random_string(20); $this->token = random_string(20);
} }
function clean() { function clean() {
$x = $this->extract_code($this->str); $x = $this->extract_code($this->str);
@ -46,6 +52,15 @@ class MarkdownSoap {
return $x; return $x;
} }
/**
* @brief Extracts code blocks and privately escapes them from processing.
*
* @see encode_code()
* @see putback_code()
*
* @param string $s
* @return string
*/
function extract_code($s) { function extract_code($s) {
$text = preg_replace_callback('{ $text = preg_replace_callback('{
@ -71,8 +86,17 @@ class MarkdownSoap {
return base64_decode($matches[1]); return base64_decode($matches[1]);
} }
/**
* @brief Put back the code blocks.
*
* @see extract_code()
* @see decode_code()
*
* @param string $s
* @return string
*/
function putback_code($s) { function putback_code($s) {
$text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm',[ $this, 'decode_code' ], $s); $text = preg_replace_callback('{' . $this->token . '\;(.*?)\;}xm', [ $this, 'decode_code' ], $s);
return $text; return $text;
} }
@ -84,20 +108,25 @@ class MarkdownSoap {
} }
function protect_autolinks($s) { function protect_autolinks($s) {
$s = preg_replace('/\<(https?\:\/\/)(.*?)\>/','[$1$2]($1$2)',$s); $s = preg_replace('/\<(https?\:\/\/)(.*?)\>/', '[$1$2]($1$2)', $s);
return $s; return $s;
} }
function unprotect_autolinks($s) { function unprotect_autolinks($s) {
return $s; return $s;
} }
function escape($s) { function escape($s) {
return htmlspecialchars($s,ENT_QUOTES,'UTF-8',false); return htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false);
} }
/**
* @brief Converts special HTML entities back to characters.
*
* @param string $s
* @return string
*/
static public function unescape($s) { static public function unescape($s) {
return htmlspecialchars_decode($s,ENT_QUOTES); return htmlspecialchars_decode($s, ENT_QUOTES);
} }
} }

View File

@ -2,12 +2,36 @@
namespace Zotlabs\Lib; namespace Zotlabs\Lib;
use \Zotlabs\Access as Zaccess; use Zotlabs\Access\PermissionRoles;
use Zotlabs\Access\Permissions;
/**
* @brief Permission Categories. Permission rules for various classes of connections.
*
* Connection permissions answer the question "Can Joe view my photos?"
*
* Some permissions may be inherited from the channel's "privacy settings"
* (@ref ::Zotlabs::Access::PermissionLimits "PermissionLimits") "Who can view my
* photos (at all)?" which have higher priority than individual connection settings.
* We evaluate permission limits first, and then fall through to connection
* permissions if the permission limits didn't already make a definitive decision.
*
* After PermissionLimits and connection permissions are evaluated, individual
* content ACLs are evaluated (@ref ::Zotlabs::Access::AccessList "AccessList").
* These answer the question "Can Joe view *this* album/photo?".
*/
class Permcat { class Permcat {
/**
* @var array
*/
private $permcats = []; private $permcats = [];
/**
* @brief Permcat constructor.
*
* @param int $channel_id
*/
public function __construct($channel_id) { public function __construct($channel_id) {
$perms = []; $perms = [];
@ -16,16 +40,16 @@ class Permcat {
$role = get_pconfig($channel_id,'system','permissions_role'); $role = get_pconfig($channel_id,'system','permissions_role');
if($role) { if($role) {
$x = Zaccess\PermissionRoles::role_perms($role); $x = PermissionRoles::role_perms($role);
if($x['perms_connect']) { if($x['perms_connect']) {
$perms = Zaccess\Permissions::FilledPerms($x['perms_connect']); $perms = Permissions::FilledPerms($x['perms_connect']);
} }
} }
// if no role perms it may be a custom role, see if there any autoperms // if no role perms it may be a custom role, see if there any autoperms
if(! $perms) { if(! $perms) {
$perms = Zaccess\Permissions::FilledAutoPerms($channel_id); $perms = Permissions::FilledAutoPerms($channel_id);
} }
// if no autoperms it may be a custom role with manual perms // if no autoperms it may be a custom role with manual perms
@ -50,13 +74,13 @@ class Permcat {
// nothing was found - create a filled permission array where all permissions are 0 // nothing was found - create a filled permission array where all permissions are 0
if(! $perms) { if(! $perms) {
$perms = Zaccess\Permissions::FilledPerms([]); $perms = Permissions::FilledPerms([]);
} }
$this->permcats[] = [ $this->permcats[] = [
'name' => 'default', 'name' => 'default',
'localname' => t('default','permcat'), 'localname' => t('default','permcat'),
'perms' => Zaccess\Permissions::Operms($perms), 'perms' => Permissions::Operms($perms),
'system' => 1 'system' => 1
]; ];
@ -67,26 +91,39 @@ class Permcat {
$this->permcats[] = [ $this->permcats[] = [
'name' => $p[$x][0], 'name' => $p[$x][0],
'localname' => $p[$x][1], 'localname' => $p[$x][1],
'perms' => Zaccess\Permissions::Operms(Zaccess\Permissions::FilledPerms($p[$x][2])), 'perms' => Permissions::Operms(Permissions::FilledPerms($p[$x][2])),
'system' => intval($p[$x][3]) 'system' => intval($p[$x][3])
]; ];
} }
} }
} }
/**
* @brief Return array with permcats.
*
* @return array
*/
public function listing() { public function listing() {
return $this->permcats; return $this->permcats;
} }
/**
* @brief
*
* @param string $name
* @return array
* * \e array with permcats
* * \e bool \b error if $name not found in permcats true
*/
public function fetch($name) { public function fetch($name) {
if($name && $this->permcats) { if($name && $this->permcats) {
foreach($this->permcats as $permcat) { foreach($this->permcats as $permcat) {
if(strcasecmp($permcat['name'],$name) === 0) { if(strcasecmp($permcat['name'], $name) === 0) {
return $permcat; return $permcat;
} }
} }
} }
return ['error' => true]; return ['error' => true];
} }
@ -120,27 +157,30 @@ class Permcat {
} }
} }
call_hooks('permcats',$permcats); /**
* @hooks permcats
* * \e array
*/
call_hooks('permcats', $permcats);
return $permcats; return $permcats;
} }
static public function find_permcat($arr,$name) { static public function find_permcat($arr, $name) {
if((! $arr) || (! $name)) if((! $arr) || (! $name))
return false; return false;
foreach($arr as $p) foreach($arr as $p)
if($p['name'] == $name) if($p['name'] == $name)
return $p['value']; return $p['value'];
} }
static public function update($channel_id, $name,$permarr) { static public function update($channel_id, $name, $permarr) {
PConfig::Set($channel_id,'permcat',$name,$permarr); PConfig::Set($channel_id, 'permcat', $name, $permarr);
} }
static public function delete($channel_id,$name) { static public function delete($channel_id, $name) {
PConfig::Delete($channel_id,'permcat',$name); PConfig::Delete($channel_id, 'permcat', $name);
} }
} }

View File

@ -1,22 +1,25 @@
<?php <?php
namespace Zotlabs\Module; namespace Zotlabs\Module;
/* require_once 'include/acl_selectors.php';
* ACL selector json backend require_once 'include/group.php';
/**
* @brief ACL selector json backend.
*
* This module provides JSON lists of connections and local/remote channels * This module provides JSON lists of connections and local/remote channels
* (xchans) to populate various tools such as the ACL (AccessControlList) popup * (xchans) to populate various tools such as the ACL (AccessControlList) popup
* and various auto-complete functions (such as email recipients, search, and * and various auto-complete functions (such as email recipients, search, and
* mention targets. * mention targets.
*
* There are two primary output structural formats. One for the ACL widget and * There are two primary output structural formats. One for the ACL widget and
* the other for auto-completion. * the other for auto-completion.
* Many of the behaviour variations are triggered on the use of single character keys *
* however this functionality has grown in an ad-hoc manner and has gotten quite messy over time. * Many of the behaviour variations are triggered on the use of single character
* keys however this functionality has grown in an ad-hoc manner and has gotten
* quite messy over time.
*/ */
require_once("include/acl_selectors.php");
require_once("include/group.php");
class Acl extends \Zotlabs\Web\Controller { class Acl extends \Zotlabs\Web\Controller {
function init() { function init() {
@ -383,8 +386,6 @@ class Acl extends \Zotlabs\Web\Controller {
'items' => $items, 'items' => $items,
); );
echo json_encode($o); echo json_encode($o);
killme(); killme();

View File

@ -35,6 +35,8 @@ class Site {
$abandon_days = ((x($_POST,'abandon_days')) ? intval(trim($_POST['abandon_days'])) : 0); $abandon_days = ((x($_POST,'abandon_days')) ? intval(trim($_POST['abandon_days'])) : 0);
$register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : ''); $register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : '');
$site_sellpage = ((x($_POST,'site_sellpage')) ? notags(trim($_POST['site_sellpage'])) : '');
$site_location = ((x($_POST,'site_location')) ? notags(trim($_POST['site_location'])) : '');
$frontpage = ((x($_POST,'frontpage')) ? notags(trim($_POST['frontpage'])) : ''); $frontpage = ((x($_POST,'frontpage')) ? notags(trim($_POST['frontpage'])) : '');
$mirror_frontpage = ((x($_POST,'mirror_frontpage')) ? intval(trim($_POST['mirror_frontpage'])) : 0); $mirror_frontpage = ((x($_POST,'mirror_frontpage')) ? intval(trim($_POST['mirror_frontpage'])) : 0);
$directory_server = ((x($_POST,'directory_server')) ? trim($_POST['directory_server']) : ''); $directory_server = ((x($_POST,'directory_server')) ? trim($_POST['directory_server']) : '');
@ -76,6 +78,8 @@ class Site {
set_config('system', 'poll_interval', $poll_interval); set_config('system', 'poll_interval', $poll_interval);
set_config('system', 'maxloadavg', $maxloadavg); set_config('system', 'maxloadavg', $maxloadavg);
set_config('system', 'frontpage', $frontpage); set_config('system', 'frontpage', $frontpage);
set_config('system', 'sellpage', $site_sellpage);
set_config('system', 'site_location', $site_location);
set_config('system', 'mirror_frontpage', $mirror_frontpage); set_config('system', 'mirror_frontpage', $mirror_frontpage);
set_config('system', 'sitename', $sitename); set_config('system', 'sitename', $sitename);
set_config('system', 'login_on_homepage', $login_on_homepage); set_config('system', 'login_on_homepage', $login_on_homepage);
@ -328,6 +332,12 @@ class Site {
'$thumbnail_security' => array('thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.")), '$thumbnail_security' => array('thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.")),
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")), '$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')), '$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
'$sellpage' => array('site_sellpage', t('Public servers: Optional landing (marketing) webpage for new registrants'), get_config('system','sellpage',''), sprintf( t('Create this page first. Default is %s/register'),z_root())),
'$location' => array('site_location', t('Optional: site location'), get_config('system','site_location',''), t('Region or country')),
'$form_security_token' => get_form_security_token("admin_site"), '$form_security_token' => get_form_security_token("admin_site"),
)); ));
} }

View File

@ -313,7 +313,7 @@ class Dirsearch extends \Zotlabs\Web\Controller {
$ret['results'] = $entries; $ret['results'] = $entries;
if($kw) { if($kw) {
$k = dir_tagadelic($kw); $k = dir_tagadelic($kw, $hub);
if($k) { if($k) {
$ret['keywords'] = array(); $ret['keywords'] = array();
foreach($k as $kv) { foreach($k as $kv) {

View File

@ -51,8 +51,8 @@ class Hq extends \Zotlabs\Web\Controller {
if(! $item_hash) { if(! $item_hash) {
$r = q("SELECT mid FROM item $r = q("SELECT mid FROM item
WHERE uid = %d WHERE uid = %d $item_normal
AND mid = parent_mid AND item_unseen = 1
ORDER BY created DESC LIMIT 1", ORDER BY created DESC LIMIT 1",
intval(local_channel()) intval(local_channel())
); );
@ -135,13 +135,11 @@ class Hq extends \Zotlabs\Web\Controller {
$o = replace_macros(get_markup_template("hq.tpl"), $o = replace_macros(get_markup_template("hq.tpl"),
[ [
'$no_messages' => (($target_item) ? false : true), '$no_messages' => (($target_item) ? false : true),
'$no_messages_label' => t('Welcome to hubzilla!') '$no_messages_label' => [ t('Welcome to Hubzilla!'), t('You have got no unseen activity...') ],
'$editor' => status_editor($a,$x)
] ]
); );
$o = '<div id="jot-popup">';
$o .= status_editor($a,$x);
$o .= '</div>';
} }
if(! $update && ! $load) { if(! $update && ! $load) {
@ -266,18 +264,15 @@ class Hq extends \Zotlabs\Web\Controller {
} }
if($r) { if($r) {
$parents_str = ids_to_querystr($r,'item_id'); $items = q("SELECT item.*, item.id AS item_id
if($parents_str) { FROM item
$items = q("SELECT item.*, item.id AS item_id WHERE parent = '%s' $item_normal ",
FROM item dbesc($r[0]['item_id'])
WHERE parent IN ( %s ) $item_normal ", );
dbesc($parents_str)
);
xchan_query($items,true,(($sys_item) ? local_channel() : 0)); xchan_query($items,true,(($sys_item) ? local_channel() : 0));
$items = fetch_post_tags($items,true); $items = fetch_post_tags($items,true);
$items = conv_sort($items,'created'); $items = conv_sort($items,'created');
}
} }
else { else {
$items = []; $items = [];

View File

@ -31,19 +31,21 @@ class Owa extends \Zotlabs\Web\Controller {
if($keyId) { if($keyId) {
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash $r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
where hubloc_addr = '%s' limit 1", where hubloc_addr = '%s' ",
dbesc(str_replace('acct:','',$keyId)) dbesc(str_replace('acct:','',$keyId))
); );
if($r) { if($r) {
$hubloc = $r[0]; foreach($r as $hubloc) {
$verified = \Zotlabs\Web\HTTPSig::verify('',$hubloc['xchan_pubkey']); $verified = \Zotlabs\Web\HTTPSig::verify('',$hubloc['xchan_pubkey']);
if($verified && $verified['header_signed'] && $verified['header_valid']) { if($verified && $verified['header_signed'] && $verified['header_valid']) {
$ret['success'] = true; $ret['success'] = true;
$token = random_string(32); $token = random_string(32);
\Zotlabs\Zot\Verify::create('owt',0,$token,$r[0]['hubloc_addr']); \Zotlabs\Zot\Verify::create('owt',0,$token,$r[0]['hubloc_addr']);
$result = ''; $result = '';
openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']); openssl_public_encrypt($token,$result,$hubloc['xchan_pubkey']);
$ret['encrypted_token'] = base64url_encode($result); $ret['encrypted_token'] = base64url_encode($result);
break;
}
} }
} }
} }

View File

@ -2,36 +2,54 @@
namespace Zotlabs\Thumbs; namespace Zotlabs\Thumbs;
require_once('library/epub-meta/epub.php'); require_once 'library/epub-meta/epub.php';
/**
* @brief Thumbnail creation for epub files.
*
*/
class Epubthumb { class Epubthumb {
/**
* @brief Match for application/epub+zip.
*
* @param string $type MimeType
* @return boolean
*/
function Match($type) { function Match($type) {
return(($type === 'application/epub+zip') ? true : false ); return(($type === 'application/epub+zip') ? true : false );
} }
function Thumb($attach,$preview_style,$height = 300, $width = 300) { /**
* @brief
*
* @param array $attach
* @param number $preview_style unused
* @param number $height (optional) default 300
* @param number $width (optional) default 300
*/
function Thumb($attach, $preview_style, $height = 300, $width = 300) {
$photo = false; $photo = false;
$ep = new \Epub(dbunescbin($attach['content'])); $ep = new \EPub(dbunescbin($attach['content']));
$data = $ep->Cover(); $data = $ep->Cover();
if($data['found']) { if($data['found']) {
$photo = $data['data']; $photo = $data['data'];
} }
if($photo) { if($photo) {
$image = imagecreatefromstring($photo); $image = imagecreatefromstring($photo);
$dest = imagecreatetruecolor( $width, $height ); $dest = imagecreatetruecolor($width, $height);
$srcwidth = imagesx($image); $srcwidth = imagesx($image);
$srcheight = imagesy($image); $srcheight = imagesy($image);
imagealphablending($dest, false); imagealphablending($dest, false);
imagesavealpha($dest, true); imagesavealpha($dest, true);
imagecopyresampled($dest, $image, 0, 0, 0, 0, $width, $height, $srcwidth, $srcheight); imagecopyresampled($dest, $image, 0, 0, 0, 0, $width, $height, $srcwidth, $srcheight);
imagedestroy($image); imagedestroy($image);
imagejpeg($dest,dbunescbin($attach['content']) . '.thumb'); imagejpeg($dest, dbunescbin($attach['content']) . '.thumb');
} }
} }
} }

View File

@ -49,6 +49,7 @@ class Video {
$cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmpfile . '[0]') . ' -thumbnail ' . $width . 'x' . $height . ' ' . escapeshellarg(PROJECT_BASE . '/' . $outfile); $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmpfile . '[0]') . ' -thumbnail ' . $width . 'x' . $height . ' ' . escapeshellarg(PROJECT_BASE . '/' . $outfile);
// logger('imagick thumbnail command: ' . $cmd); // logger('imagick thumbnail command: ' . $cmd);
/** @scrutinizer ignore-unhandled */
@exec($cmd); @exec($cmd);
if(! file_exists($outfile)) { if(! file_exists($outfile)) {

View File

@ -11,8 +11,8 @@ class Forums {
$o = ''; $o = '';
if(is_array($arr) && array_key_exists('limit',$arr)) if(is_array($arr) && array_key_exists('limit',$arr) && intval($arr['limit']) >= 0)
$limit = " limit " . intval($limit) . " "; $limit = " limit " . intval($arr['limit']) . " ";
else else
$limit = ''; $limit = '';

View File

@ -3,4 +3,4 @@ url: $baseurl/articles/$nick
name: Articles name: Articles
requires: local_channel, articles requires: local_channel, articles
photo: icon:file-text-o photo: icon:file-text-o
categories: Productivity categories: nav_featured_app, Productivity

View File

@ -3,4 +3,4 @@ url: $baseurl/cards/$nick
name: Cards name: Cards
requires: local_channel, cards requires: local_channel, cards
photo: icon:list photo: icon:list
categories: Productivity categories: nav_featured_app, Productivity

View File

@ -3,4 +3,4 @@ url: $baseurl/webpages/$nick
requires: local_channel, webpages requires: local_channel, webpages
name: Webpages name: Webpages
photo: icon:newspaper-o photo: icon:newspaper-o
categories: Productivity categories: nav_featured_app, Productivity

View File

@ -3,4 +3,4 @@ url: $baseurl/wiki/$nick
requires: local_channel, wiki requires: local_channel, wiki
name: Wiki name: Wiki
photo: icon:pencil-square-o photo: icon:pencil-square-o
categories: Productivity categories: nav_featured_app, Productivity

View File

@ -2010,7 +2010,7 @@ function build_querystring($params, $name = null) {
} }
/* /**
* @brief Much better way of dealing with c-style args. * @brief Much better way of dealing with c-style args.
*/ */
function argc() { function argc() {
@ -2031,6 +2031,8 @@ function dba_timer() {
/** /**
* @brief Returns xchan_hash from the observer. * @brief Returns xchan_hash from the observer.
* *
* Observer can be a local or remote channel.
*
* @return string xchan_hash from observer, otherwise empty string if no observer * @return string xchan_hash from observer, otherwise empty string if no observer
*/ */
function get_observer_hash() { function get_observer_hash() {
@ -2041,7 +2043,6 @@ function get_observer_hash() {
return ''; return '';
} }
/** /**
* @brief Returns the complete URL of the current page, e.g.: http(s)://something.com/network * @brief Returns the complete URL of the current page, e.g.: http(s)://something.com/network
* *

View File

@ -47,7 +47,10 @@ function uninstall_plugin($plugin) {
} }
/** /**
* @brief installs an addon. * @brief Installs an addon.
*
* This function is called once to install the addon (either from the cli or via
* the web admin). This will also call load_plugin() once.
* *
* @param string $plugin name of the addon * @param string $plugin name of the addon
* @return bool * @return bool
@ -188,7 +191,9 @@ function visible_plugin_list() {
/** /**
* @brief registers a hook. * @brief Registers a hook.
*
* @see ::Zotlabs::Extend::Hook::register()
* *
* @param string $hook the name of the hook * @param string $hook the name of the hook
* @param string $file the name of the file that hooks into * @param string $file the name of the file that hooks into
@ -219,6 +224,8 @@ function register_hook($hook, $file, $function, $priority = 0) {
/** /**
* @brief unregisters a hook. * @brief unregisters a hook.
* *
* @see ::Zotlabs::Extend::Hook::unregister
*
* @param string $hook the name of the hook * @param string $hook the name of the hook
* @param string $file the name of the file that hooks into * @param string $file the name of the file that hooks into
* @param string $function the name of the function that the hook called * @param string $function the name of the function that the hook called

View File

@ -178,11 +178,12 @@ function poco_load($xchan = '', $url = null) {
); );
if(! $r) { if(! $r) {
q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', 0 ) ", q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values ( '%s', '%s', %d, '%s', '%s', '%s', 0 ) ",
dbesc($xchan), dbesc($xchan),
dbesc($hash), dbesc($hash),
intval(0), intval(0),
dbesc(''), dbesc(''),
dbesc(''),
dbesc(datetime_convert()) dbesc(datetime_convert())
); );
} }

View File

@ -309,19 +309,27 @@ function article_tagadelic($uid, $count = 0, $authors = '', $owner = '', $flags
function dir_tagadelic($count = 0) { function dir_tagadelic($count = 0, $hub = '') {
$count = intval($count); $count = intval($count);
$dirmode = get_config('system','directory_mode'); $dirmode = get_config('system','directory_mode');
if($dirmode == DIRECTORY_MODE_STANDALONE) { if(($dirmode == DIRECTORY_MODE_STANDALONE) && (! $hub)) {
$hub = \App::get_hostname();
}
if($hub)
$hub_query = " and xtag_hash in (select hubloc_hash from hubloc where hubloc_host = '" . protect_sprintf(dbesc($hub)) . "') ";
else
$hub_query = '';
if($hub_query) {
// Fetch tags // Fetch tags
$r = q("select xtag_term as term, count(xtag_term) as total from xtag $r = q("select xtag_term as term, count(xtag_term) as total from xtag
left join hubloc on xtag_hash = hubloc_hash left join hubloc on xtag_hash = hubloc_hash
where xtag_flags = 0 and hubloc_url = '%s' where xtag_flags = 0 $hub_query
group by xtag_term order by total desc %s", group by xtag_term order by total desc %s",
dbesc(z_root()),
((intval($count)) ? "limit $count" : '') ((intval($count)) ? "limit $count" : '')
); );
} }
@ -485,9 +493,6 @@ function dir_tagblock($link,$r) {
$o = ''; $o = '';
$observer = get_observer_hash(); $observer = get_observer_hash();
if(! get_directory_setting($observer, 'globaldir'))
return $o;
if(! $r) if(! $r)
$r = App::$data['directory_keywords']; $r = App::$data['directory_keywords'];

View File

@ -24,12 +24,20 @@ define('RANDOM_STRING_TEXT', 0x01 );
* @return string substituted string * @return string substituted string
*/ */
function replace_macros($s, $r) { function replace_macros($s, $r) {
$arr = [
'template' => $s,
'params' => $r
];
$arr = array('template' => $s, 'params' => $r); /**
* @hooks replace_macros
* * \e string \b template
* * \e array \b params
*/
call_hooks('replace_macros', $arr); call_hooks('replace_macros', $arr);
$t = App::template_engine(); $t = App::template_engine();
$output = $t->replace_macros($arr['template'],$arr['params']); $output = $t->replace_macros($arr['template'], $arr['params']);
return $output; return $output;
} }
@ -301,12 +309,16 @@ function purify_html($s, $allow_position = false) {
/** /**
* @brief generate a string that's random, but usually pronounceable. * @brief Generate a string that's random, but usually pronounceable.
* *
* Used to generate initial passwords. * Used to generate initial passwords.
* *
* @param int $len * @note In order to create "pronounceable" strings some consonant pairs or
* @return string * letters that does not make a very good word ending are chopped off, so that
* the returned string length can be lower than $len.
*
* @param int $len max length of generated string
* @return string Genereated random, but usually pronounceable string
*/ */
function autoname($len) { function autoname($len) {
@ -343,6 +355,7 @@ function autoname($len) {
$midcons = array('ck','ct','gn','ld','lf','lm','lt','mb','mm', 'mn','mp', $midcons = array('ck','ct','gn','ld','lf','lm','lt','mb','mm', 'mn','mp',
'nd','ng','nk','nt','rn','rp','rt'); 'nd','ng','nk','nt','rn','rp','rt');
// avoid these consonant pairs at the end of the string
$noend = array('bl', 'br', 'cl','cr','dr','fl','fr','gl','gr', $noend = array('bl', 'br', 'cl','cr','dr','fl','fr','gl','gr',
'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh'); 'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh');
@ -355,7 +368,7 @@ function autoname($len) {
$word = ''; $word = '';
for ($x = 0; $x < $len; $x ++) { for ($x = 0; $x < $len; $x ++) {
$r = mt_rand(0,count($table) - 1); $r = mt_rand(0, count($table) - 1);
$word .= $table[$r]; $word .= $table[$r];
if ($table == $vowels) if ($table == $vowels)
@ -364,14 +377,15 @@ function autoname($len) {
$table = $vowels; $table = $vowels;
} }
$word = substr($word,0,$len); $word = substr($word, 0, $len);
foreach ($noend as $noe) { foreach ($noend as $noe) {
if ((strlen($word) > 2) && (substr($word,-2) == $noe)) { if ((strlen($word) > 2) && (substr($word, -2) == $noe)) {
$word = substr($word,0,-1); $word = substr($word, 0, -1);
break; break;
} }
} }
// avoid the letter 'q' as it does not make a very good word ending
if (substr($word, -1) == 'q') if (substr($word, -1) == 'q')
$word = substr($word, 0, -1); $word = substr($word, 0, -1);
@ -1094,17 +1108,19 @@ function sslify($s) {
return $s; return $s;
} }
/**
* @brief Get an array of poke verbs.
*
* @return array
* * \e index is present tense verb
* * \e value is array containing past tense verb, translation of present, translation of past
*/
function get_poke_verbs() { function get_poke_verbs() {
// index is present tense verb if (get_config('system', 'poke_basic')) {
// value is array containing past tense verb, translation of present, translation of past
if(get_config('system','poke_basic')) {
$arr = array( $arr = array(
'poke' => array( 'poked', t('poke'), t('poked')), 'poke' => array('poked', t('poke'), t('poked')),
); );
} } else {
else {
$arr = array( $arr = array(
'poke' => array( 'poked', t('poke'), t('poked')), 'poke' => array( 'poked', t('poke'), t('poked')),
'ping' => array( 'pinged', t('ping'), t('pinged')), 'ping' => array( 'pinged', t('ping'), t('pinged')),
@ -1114,15 +1130,26 @@ function get_poke_verbs() {
'rebuff' => array( 'rebuffed', t('rebuff'), t('rebuffed')), 'rebuff' => array( 'rebuffed', t('rebuff'), t('rebuffed')),
); );
/**
* @hooks poke_verbs
* * \e array associative array with another array as value
*/
call_hooks('poke_verbs', $arr); call_hooks('poke_verbs', $arr);
} }
return $arr; return $arr;
} }
/**
* @brief Get an array of mood verbs.
*
* @return array
* * \e index is the verb
* * \e value is the translated verb
*/
function get_mood_verbs() { function get_mood_verbs() {
$arr = array( $arr = [
'happy' => t('happy'), 'happy' => t('happy'),
'sad' => t('sad'), 'sad' => t('sad'),
'mellow' => t('mellow'), 'mellow' => t('mellow'),
@ -1144,9 +1171,14 @@ function get_mood_verbs() {
'motivated' => t('motivated'), 'motivated' => t('motivated'),
'relaxed' => t('relaxed'), 'relaxed' => t('relaxed'),
'surprised' => t('surprised'), 'surprised' => t('surprised'),
); ];
/**
* @hooks mood_verbs
* * \e array associative array with mood verbs
*/
call_hooks('mood_verbs', $arr); call_hooks('mood_verbs', $arr);
return $arr; return $arr;
} }
@ -1513,14 +1545,37 @@ function format_filer(&$item) {
function generate_map($coord) { function generate_map($coord) {
$coord = trim($coord); $coord = trim($coord);
$coord = str_replace(array(',','/',' '),array(' ',' ',' '),$coord); $coord = str_replace(array(',','/',' '),array(' ',' ',' '),$coord);
$arr = array('lat' => trim(substr($coord,0,strpos($coord,' '))), 'lon' => trim(substr($coord,strpos($coord,' ')+1)), 'html' => '');
call_hooks('generate_map',$arr); $arr = [
'lat' => trim(substr($coord, 0, strpos($coord, ' '))),
'lon' => trim(substr($coord, strpos($coord, ' ')+1)),
'html' => ''
];
/**
* @hooks generate_map
* * \e string \b lat
* * \e string \b lon
* * \e string \b html the parsed HTML to return
*/
call_hooks('generate_map', $arr);
return (($arr['html']) ? $arr['html'] : $coord); return (($arr['html']) ? $arr['html'] : $coord);
} }
function generate_named_map($location) { function generate_named_map($location) {
$arr = array('location' => $location, 'html' => ''); $arr = [
call_hooks('generate_named_map',$arr); 'location' => $location,
'html' => ''
];
/**
* @hooks generate_named_map
* * \e string \b location
* * \e string \b html the parsed HTML to return
*/
call_hooks('generate_named_map', $arr);
return (($arr['html']) ? $arr['html'] : $location); return (($arr['html']) ? $arr['html'] : $location);
} }
@ -1626,13 +1681,11 @@ function prepare_binary($item) {
} }
/** /**
* @brief Given a text string, convert from bbcode to html and add smilie icons. * @brief Given a text string, convert from bbcode to html and add smilie icons.
* *
* @param string $text * @param string $text
* @param sting $content_type (optional) default text/bbcode * @param string $content_type (optional) default text/bbcode
* @param boolean $cache (optional) default false * @param boolean $cache (optional) default false
* *
* @return string * @return string
@ -3033,8 +3086,19 @@ function text_highlight($s, $lang) {
$s = jindent($s); $s = jindent($s);
} }
$arr = [ 'text' => $s, 'language' => $lang, 'success' => false ]; $arr = [
call_hooks('text_highlight',$arr); 'text' => $s,
'language' => $lang,
'success' => false
];
/**
* @hooks text_highlight
* * \e string \b text
* * \e string \b language
* * \e boolean \b success default false
*/
call_hooks('text_highlight', $arr);
if($arr['success']) if($arr['success'])
$o = $arr['text']; $o = $arr['text'];
@ -3117,7 +3181,6 @@ function share_unshield($m) {
function cleanup_bbcode($body) { function cleanup_bbcode($body) {
/** /**
* fix naked links by passing through a callback to see if this is a hubzilla site * fix naked links by passing through a callback to see if this is a hubzilla site
* (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both. * (already known to us) which will get a zrl, otherwise link with url, add bookmark tag to both.
@ -3155,7 +3218,6 @@ function cleanup_bbcode($body) {
return $body; return $body;
} }
function gen_link_id($mid) { function gen_link_id($mid) {

1
view/de Symbolic link
View File

@ -0,0 +1 @@
de-de

View File

@ -173,11 +173,7 @@ ACL.prototype.on_custom = function(event) {
that.deny_cid = []; that.deny_cid = [];
that.deny_gid = []; that.deny_gid = [];
$("#acl-list-content .acl-list-item img[data-src]").each(function(i, el) { datasrc2src('#acl-list-content .acl-list-item img[data-src]');
//Replace data-src attribute with src attribute for every image
$(el).attr('src', $(el).data("src"));
$(el).removeAttr("data-src");
});
that.update_view('custom'); that.update_view('custom');
that.on_submit(); that.on_submit();

View File

@ -92,6 +92,13 @@ $(document).ready(function() {
}); });
function datasrc2src(selector) {
$(selector).each(function(i, el) {
$(el).attr("src", $(el).data("src"));
$(el).removeAttr("data-src");
});
}
function confirmDelete() { function confirmDelete() {
return confirm(aStr.delitem); return confirm(aStr.delitem);
} }

View File

@ -71,6 +71,9 @@
{{include file="field_select.tpl" field=$register_policy}} {{include file="field_select.tpl" field=$register_policy}}
{{include file="field_checkbox.tpl" field=$invite_only}} {{include file="field_checkbox.tpl" field=$invite_only}}
{{include file="field_select.tpl" field=$access_policy}} {{include file="field_select.tpl" field=$access_policy}}
{{include file="field_input.tpl" field=$location}}
{{include file="field_input.tpl" field=$sellpage}}
<div class="submit"><input type="submit" name="page_site" value="{{$submit}}" /></div> <div class="submit"><input type="submit" name="page_site" value="{{$submit}}" /></div>
<h3>{{$corporate}}</h3> <h3>{{$corporate}}</h3>

View File

@ -1,9 +1,14 @@
{{if $no_messages}} {{if $no_messages}}
<div class="alert alert-warning alert-dismissible fade show" role="alert"> <div class="alert alert-warning alert-dismissible fade show" role="alert">
{{$no_messages_label}}
<button type="button" class="close" data-dismiss="alert" aria-label="Close"> <button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
<h3>{{$no_messages_label.0}}</h3>
<br>
{{$no_messages_label.1}}
</div> </div>
{{/if}} {{/if}}
<div id="jot-popup">
{{$editor}}
</div>