💡 Improving Doxygen documentation.

Fix some Doxygen parsing errors.
Improve hooks documentation.
This commit is contained in:
Klaus Weidenbach 2017-09-05 00:23:42 +02:00
parent 0ce7358f0f
commit 1a737be2b4
26 changed files with 2164 additions and 1254 deletions

View file

@ -1,12 +1,21 @@
<?php
namespace Zotlabs\Access;
use Zotlabs\Lib as Zlib;
/**
* @brief PermissionRoles class.
*
* @see Permissions
*/
class PermissionRoles {
/**
* @brief PermissionRoles version.
*
* This must match the version in Permissions.php before permission updates can run.
*
* @return number
*/
static public function version() {
return 2;
}
@ -23,12 +32,13 @@ class PermissionRoles {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = true;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'chat', 'post_like', 'republish' ];
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'chat', 'post_like', 'republish'
];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'social_restricted':
@ -36,11 +46,11 @@ class PermissionRoles {
$ret['default_collection'] = true;
$ret['directory_publish'] = true;
$ret['online'] = true;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'chat', 'post_like' ];
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'chat', 'post_like'
];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
@ -50,10 +60,11 @@ class PermissionRoles {
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like' ];
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like'
];
$ret['limits'] = PermissionLimits::Std_Limits();
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
$ret['limits']['view_storage'] = PERMS_SPECIFIC;
@ -65,12 +76,13 @@ class PermissionRoles {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'post_wall', 'post_comments', 'tag_deliver',
'post_mail', 'post_like' , 'republish', 'chat' ];
'post_mail', 'post_like' , 'republish', 'chat'
];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'forum_restricted':
@ -78,11 +90,10 @@ class PermissionRoles {
$ret['default_collection'] = true;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'post_wall', 'post_comments', 'tag_deliver',
'post_mail', 'post_like' , 'chat' ];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
@ -92,12 +103,11 @@ class PermissionRoles {
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'post_wall', 'post_comments',
'post_mail', 'post_like' , 'chat' ];
'post_mail', 'post_like' , 'chat'
];
$ret['limits'] = PermissionLimits::Std_Limits();
$ret['limits']['view_profile'] = PERMS_SPECIFIC;
$ret['limits']['view_contacts'] = PERMS_SPECIFIC;
@ -112,12 +122,11 @@ class PermissionRoles {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like' , 'republish' ];
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like' , 'republish'
];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
@ -127,11 +136,11 @@ class PermissionRoles {
$ret['default_collection'] = true;
$ret['directory_publish'] = false;
$ret['online'] = false;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like' , 'republish' ];
'view_pages', 'view_wiki', 'send_stream', 'post_wall', 'post_comments',
'post_mail', 'post_like' , 'republish'
];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
@ -141,11 +150,10 @@ class PermissionRoles {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'post_like' , 'republish' ];
'view_pages', 'view_wiki', 'post_like' , 'republish'
];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
@ -155,13 +163,13 @@ class PermissionRoles {
$ret['default_collection'] = false;
$ret['directory_publish'] = true;
$ret['online'] = false;
$ret['perms_connect'] = [
$ret['perms_connect'] = [
'view_stream', 'view_profile', 'view_contacts', 'view_storage',
'view_pages', 'view_wiki', 'write_storage', 'write_pages', 'post_wall', 'post_comments', 'tag_deliver',
'post_mail', 'post_like' , 'republish', 'chat', 'write_wiki' ];
'post_mail', 'post_like' , 'republish', 'chat', 'write_wiki'
];
$ret['limits'] = PermissionLimits::Std_Limits();
break;
case 'custom':
@ -170,11 +178,15 @@ class PermissionRoles {
}
$x = get_config('system','role_perms');
// let system settings over-ride any or all
// let system settings over-ride any or all
if($x && is_array($x) && array_key_exists($role,$x))
$ret = array_merge($ret,$x[$role]);
call_hooks('get_role_perms',$ret);
/**
* @hooks get_role_perms
* * \e array
*/
call_hooks('get_role_perms', $ret);
return $ret;
}
@ -187,10 +199,10 @@ class PermissionRoles {
// \Zotlabs\Access\PermissionLimits::Set($uid,$perm,1);
if($perm === 'view_wiki')
\Zotlabs\Access\PermissionLimits::Set($uid,$perm,PERMS_PUBLIC);
\Zotlabs\Access\PermissionLimits::Set($uid, $perm, PERMS_PUBLIC);
if($perm === 'write_wiki')
\Zotlabs\Access\PermissionLimits::Set($uid,$perm,PERMS_SPECIFIC);
\Zotlabs\Access\PermissionLimits::Set($uid, $perm, PERMS_SPECIFIC);
// set autoperms here if applicable
@ -213,8 +225,6 @@ class PermissionRoles {
if($c) {
set_abconfig($uid,$c['channel_hash'],'autoperms',$perm,$value);
}
}
// now set something for all existing connections.
@ -242,38 +252,44 @@ class PermissionRoles {
}
}
/**
* @brief Array with translated role names and grouping.
*
* Return an associative array with grouped role names that can be used
* to create select groups like in \e field_select_grouped.tpl.
*
* @return array
*/
static public function roles() {
$roles = [
$roles = [
t('Social Networking') => [
'social' => t('Social - Mostly Public'),
'social_restricted' => t('Social - Restricted'),
'social' => t('Social - Mostly Public'),
'social_restricted' => t('Social - Restricted'),
'social_private' => t('Social - Private')
],
t('Community Forum') => [
'forum' => t('Forum - Mostly Public'),
'forum_restricted' => t('Forum - Restricted'),
'forum' => t('Forum - Mostly Public'),
'forum_restricted' => t('Forum - Restricted'),
'forum_private' => t('Forum - Private')
],
t('Feed Republish') => [
'feed' => t('Feed - Mostly Public'),
'feed' => t('Feed - Mostly Public'),
'feed_restricted' => t('Feed - Restricted')
],
t('Special Purpose') => [
'soapbox' => t('Special - Celebrity/Soapbox'),
'soapbox' => t('Special - Celebrity/Soapbox'),
'repository' => t('Special - Group Repository')
],
t('Other') => [
'custom' => t('Custom/Expert Mode')
]
];
return $roles;
return $roles;
}
}

View file

@ -33,19 +33,22 @@ use Zotlabs\Lib as Zlib;
*/
class Permissions {
/**
* @brief Permissions version.
*
* This must match the version in PermissionRoles.php before permission updates can run.
*
* @return number
*/
static public function version() {
// This must match the version in PermissionRoles.php before permission updates can run.
return 2;
}
/**
* @brief Return an array with Permissions.
*
* @hooks permissions_list
* * \e array \b permissions
* * \e string \b filter
* @param string $filter (optional) only passed to hook permission_list
* @return Associative array with permissions and short description.
* @param string $filter (optional) only passed to hook permissions_list
* @return array Associative array with permissions and short description.
*/
static public function Perms($filter = '') {
@ -74,6 +77,11 @@ class Permissions {
'permissions' => $perms,
'filter' => $filter
];
/**
* @hooks permissions_list
* * \e array \b permissions
* * \e string \b filter
*/
call_hooks('permissions_list', $x);
return($x['permissions']);
@ -84,9 +92,7 @@ class Permissions {
*
* e.g. you must be authenticated.
*
* @hooks write_perms
* * \e array \b permissions
* @return Associative array with permissions and short description.
* @return array Associative array with permissions and short description.
*/
static public function BlockedAnonPerms() {
@ -99,6 +105,10 @@ class Permissions {
}
$x = ['permissions' => $res];
/**
* @hooks write_perms
* * \e array \b permissions
*/
call_hooks('write_perms', $x);
return($x['permissions']);
@ -138,7 +148,7 @@ class Permissions {
* to [ 0 => ['name' => 'view_stream', 'value' => 1], ... ]
*
* @param array $arr associative perms array 'view_stream' => 1
* @return Indexed array with elements that look like
* @return array Indexed array with elements that look like
* * \e string \b name the perm name (e.g. view_stream)
* * \e int \b value the value of the perm (e.g. 1)
*/
@ -197,11 +207,10 @@ class Permissions {
* @brief
*
* @param int $channel_id A channel id
* @return associative array
* @return array Associative array with
* * \e array \b perms Permission array
* * \e int \b automatic 0 or 1
*/
static public function connect_perms($channel_id) {
$my_perms = [];

View file

@ -2,7 +2,12 @@
namespace Zotlabs\Extend;
use App;
/**
* @brief Hook class.
*
*/
class Hook {
static public function register($hook,$file,$function,$version = 1,$priority = 0) {
@ -64,11 +69,14 @@ class Hook {
return $r;
}
// unregister all hooks with this file component.
// Useful for addon upgrades where you want to clean out old interfaces.
/**
* @brief Unregister all hooks with this file component.
*
* Useful for addon upgrades where you want to clean out old interfaces.
*
* @param string $file
*/
static public function unregister_by_file($file) {
$r = q("DELETE FROM hook WHERE file = '%s' ",
dbesc($file)
);
@ -76,7 +84,6 @@ class Hook {
return $r;
}
/**
* @brief Inserts a hook into a page request.
*
@ -98,7 +105,6 @@ class Hook {
* @param int $priority
* currently not implemented in this function, would require the hook array to be resorted
*/
static public function insert($hook, $fn, $version = 0, $priority = 0) {
if(is_array($fn)) {
$fn = serialize($fn);

View file

@ -2,6 +2,11 @@
namespace Zotlabs\Lib;
/**
* @brief ActivityStreams class.
*
* Parses an ActivityStream JSON string.
*/
class ActivityStreams {
public $data;
@ -19,9 +24,16 @@ class ActivityStreams {
public $recips = null;
public $raw_recips = null;
/**
* @brief Constructor for ActivityStreams.
*
* Takes a JSON string as parameter, decodes it and sets up this object.
*
* @param string $string
*/
function __construct($string) {
$this->data = json_decode($string,true);
$this->data = json_decode($string, true);
if($this->data) {
$this->valid = true;
}
@ -50,6 +62,11 @@ class ActivityStreams {
}
}
/**
* @brief Return if instantiated ActivityStream is valid.
*
* @return boolean Return true if the JSON string could be decoded.
*/
function is_valid() {
return $this->valid;
}
@ -58,18 +75,26 @@ class ActivityStreams {
$this->saved_recips = $arr;
}
function collect_recips($base = '',$namespace = '') {
/**
* @brief Collects all recipients.
*
* @param string $base
* @param string $namespace (optional) default empty
* @return array
*/
function collect_recips($base = '', $namespace = '') {
$x = [];
$fields = [ 'to','cc','bto','bcc','audience'];
$fields = [ 'to', 'cc', 'bto', 'bcc', 'audience'];
foreach($fields as $f) {
$y = $this->get_compound_property($f,$base,$namespace);
$y = $this->get_compound_property($f, $base, $namespace);
if($y) {
$x = array_merge($x,$y);
$x = array_merge($x, $y);
if(! is_array($this->raw_recips))
$this->raw_recips = [];
$this->raw_recips[$f] = $x;
}
}
}
// not yet ready for prime time
// $x = $this->expand($x,$base,$namespace);
return $x;
@ -96,23 +121,30 @@ class ActivityStreams {
}
}
// @fixme de-duplicate
/// @fixme de-duplicate
return $ret;
}
function get_namespace($base,$namespace) {
/**
* @brief
*
* @param array $base
* @param string $namespace if not set return empty string
* @return string|NULL
*/
function get_namespace($base, $namespace) {
if(! $namespace)
return '';
$key = null;
foreach( [ $this->data, $base ] as $b ) {
if(! $b)
continue;
if(array_key_exists('@context',$b)) {
if(array_key_exists('@context', $b)) {
if(is_array($b['@context'])) {
foreach($b['@context'] as $ns) {
if(is_array($ns)) {
@ -135,19 +167,35 @@ class ActivityStreams {
}
}
}
return $key;
}
function get_property_obj($property,$base = '',$namespace = '' ) {
$prefix = $this->get_namespace($base,$namespace);
/**
* @brief
*
* @param string $property
* @param array $base (optional)
* @param string $namespace (optional) default empty
* @return NULL|mixed
*/
function get_property_obj($property, $base = '', $namespace = '') {
$prefix = $this->get_namespace($base, $namespace);
if($prefix === null)
return null;
return null;
$base = (($base) ? $base : $this->data);
$propname = (($prefix) ? $prefix . ':' : '') . $property;
return ((array_key_exists($propname,$base)) ? $base[$propname] : null);
return ((array_key_exists($propname, $base)) ? $base[$propname] : null);
}
/**
* @brief Fetches a property from an URL.
*
* @param string $url
* @return NULL|mixed
*/
function fetch_property($url) {
$redirects = 0;
if(! check_siteallowed($url)) {
@ -155,44 +203,70 @@ class ActivityStreams {
return null;
}
$x = z_fetch_url($url,true,$redirects,
$x = z_fetch_url($url, true, $redirects,
['headers' => [ 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/activity+json' ]]);
if($x['success'])
return json_decode($x['body'],true);
return json_decode($x['body'], true);
return null;
}
function get_compound_property($property,$base = '',$namespace = '') {
$x = $this->get_property_obj($property,$base,$namespace);
/**
* @brief
*
* @param string $property
* @param array $base
* @param string $namespace (optional) default empty
* @return NULL|mixed
*/
function get_compound_property($property, $base = '', $namespace = '') {
$x = $this->get_property_obj($property, $base, $namespace);
if($this->is_url($x)) {
$x = $this->fetch_property($x);
$x = $this->fetch_property($x);
}
return $x;
}
/**
* @brief Check if string starts with http.
*
* @param string $url
* @return boolean
*/
function is_url($url) {
if(($url) && (! is_array($url)) && (strpos($url,'http') === 0)) {
if(($url) && (! is_array($url)) && (strpos($url, 'http') === 0)) {
return true;
}
return false;
}
function get_primary_type($base = '',$namespace = '') {
/**
* @brief Gets the type property.
*
* @param array $base
* @param string $namespace (optional) default empty
* @return NULL|mixed
*/
function get_primary_type($base = '', $namespace = '') {
if(! $base)
$base = $this->data;
$x = $this->get_property_obj('type',$base,$namespace);
$x = $this->get_property_obj('type', $base, $namespace);
if(is_array($x)) {
foreach($x as $y) {
if(strpos($y,':') === false) {
if(strpos($y, ':') === false) {
return $y;
}
}
}
return $x;
}
function debug() {
$x = var_export($this,true);
$x = var_export($this, true);
return $x;
}

View file

@ -2,22 +2,18 @@
namespace Zotlabs\Lib;
/**
* @brief Chat related functions.
* @brief A class with chatroom related static methods.
*/
class Chatroom {
/**
* @brief Creates a chatroom.
*
* @param array $channel
* @param array $arr
* @return An associative array containing:
* - success: A boolean
* - message: (optional) A string
* @return array An associative array containing:
* * \e boolean \b success - A boolean success status
* * \e string \b message - (optional) A string
*/
static public function create($channel, $arr) {
$ret = array('success' => false);
@ -150,8 +146,8 @@ class Chatroom {
}
if(intval($x[0]['cr_expire'])) {
$r = q("delete from chat where created < %s - INTERVAL %s and chat_room = %d",
db_utcnow(),
$r = q("delete from chat where created < %s - INTERVAL %s and chat_room = %d",
db_utcnow(),
db_quoteinterval( intval($x[0]['cr_expire']) . ' MINUTE' ),
intval($x[0]['cr_id'])
);
@ -225,10 +221,16 @@ class Chatroom {
}
/**
* create a chat message via API.
* @brief Create a chat message via API.
*
* It is the caller's responsibility to enter the room.
*/
*
* @param int $uid
* @param int $room_id
* @param string $xchan
* @param string $text
* @return array
*/
static public function message($uid, $room_id, $xchan, $text) {
$ret = array('success' => false);
@ -245,12 +247,18 @@ class Chatroom {
if(! $r)
return $ret;
$arr = array(
$arr = [
'chat_room' => $room_id,
'chat_xchan' => $xchan,
'chat_text' => $text
);
];
/**
* @hooks chat_message
* Called to create a chat message.
* * \e int \b chat_room
* * \e string \b chat_xchan
* * \e string \b chat_text
*/
call_hooks('chat_message', $arr);
$x = q("insert into chat ( chat_room, chat_xchan, created, chat_text )

View file

@ -1,4 +1,4 @@
<?php /** @file */
<?php
namespace Zotlabs\Lib;
@ -14,7 +14,6 @@ class Config {
* @param string $family
* The category of the configuration value
*/
static public function Load($family) {
if(! array_key_exists($family, \App::$config))
\App::$config[$family] = array();
@ -30,7 +29,7 @@ class Config {
}
\App::$config[$family]['config_loaded'] = true;
}
}
}
}
/**
@ -47,8 +46,7 @@ class Config {
* @return mixed
* Return the set value, or false if the database update failed
*/
static public function Set($family,$key,$value) {
static public function Set($family, $key, $value) {
// manage array value
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
@ -76,8 +74,8 @@ class Config {
\App::$config[$family][$key] = $value;
$ret = $value;
}
return $ret;
return $ret;
}
/**
@ -88,25 +86,25 @@ class Config {
* $key from a cached storage in App::$config[$family]. If a key is found in the
* DB but does not exist in local config cache, pull it into the cache so we
* do not have to hit the DB again for this item.
*
*
* Returns false if not set.
*
* @param string $family
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param string $default (optional) default false
* @return mixed Return value or false on error or if not set
*/
static public function Get($family,$key,$default = false) {
static public function Get($family, $key, $default = false) {
if((! array_key_exists($family, \App::$config)) || (! array_key_exists('config_loaded', \App::$config[$family])))
self::Load($family);
if(array_key_exists('config_loaded', \App::$config[$family])) {
if(! array_key_exists($key, \App::$config[$family])) {
return $default;
return $default;
}
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
return ((! is_array(\App::$config[$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$family][$key]))
? unserialize(\App::$config[$family][$key])
: \App::$config[$family][$key]
);
@ -127,17 +125,18 @@ class Config {
* The configuration key to delete
* @return mixed
*/
static public function Delete($family,$key) {
static public function Delete($family, $key) {
$ret = false;
if(array_key_exists($family, \App::$config) && array_key_exists($key, \App::$config[$family]))
unset(\App::$config[$family][$key]);
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
$ret = q("DELETE FROM config WHERE cat = '%s' AND k = '%s'",
dbesc($family),
dbesc($key)
);
return $ret;
}
@ -154,12 +153,12 @@ class Config {
* The configuration key to query
* @return mixed
*/
static private function get_from_storage($family,$key) {
$ret = q("SELECT * FROM config WHERE cat = '%s' AND k = '%s' LIMIT 1",
dbesc($family),
dbesc($key)
);
return $ret;
}

View file

@ -1,8 +1,21 @@
<?php /** @file */
<?php
namespace Zotlabs\Lib;
/**
* @brief Class for handling channel specific configurations.
*
* <b>PConfig</b> is used for channel specific configurations and takes a
* <i>channel_id</i> as identifier. It stores for example which features are
* enabled per channel. The storage is of size MEDIUMTEXT.
*
* @code{.php}$var = Zotlabs\Lib\PConfig::Get('uid', 'category', 'key');
* // with default value for non existent key
* $var = Zotlabs\Lib\PConfig::Get('uid', 'category', 'unsetkey', 'defaultvalue');@endcode
*
* The old (deprecated?) way to access a PConfig value is:
* @code{.php}$var = get_pconfig(local_channel(), 'category', 'key');@endcode
*/
class PConfig {
/**
@ -13,9 +26,8 @@ class PConfig {
*
* @param string $uid
* The channel_id
* @return void|false Nothing or false if $uid is false
* @return void|false Nothing or false if $uid is null or false
*/
static public function Load($uid) {
if(is_null($uid) || $uid === false)
return false;
@ -64,11 +76,11 @@ class PConfig {
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param boolean $instore (deprecated, without function)
* @param mixed $default (optional, default false)
* Default value to return if key does not exist
* @return mixed Stored value or false if it does not exist
*/
static public function Get($uid,$family,$key,$default = false) {
static public function Get($uid, $family, $key, $default = false) {
if(is_null($uid) || $uid === false)
return $default;
@ -79,11 +91,10 @@ class PConfig {
if((! array_key_exists($family, \App::$config[$uid])) || (! array_key_exists($key, \App::$config[$uid][$family])))
return $default;
return ((! is_array(\App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$uid][$family][$key]))
return ((! is_array(\App::$config[$uid][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$uid][$family][$key]))
? unserialize(\App::$config[$uid][$family][$key])
: \App::$config[$uid][$family][$key]
);
}
/**
@ -102,12 +113,11 @@ class PConfig {
* The value to store
* @return mixed Stored $value or false
*/
static public function Set($uid, $family, $key, $value) {
// this catches subtle errors where this function has been called
// this catches subtle errors where this function has been called
// with local_channel() when not logged in (which returns false)
// and throws an error in array_key_exists below.
// and throws an error in array_key_exists below.
// we provide a function backtrace in the logs so that we can find
// and fix the calling function.
@ -132,7 +142,6 @@ class PConfig {
dbesc($key),
dbesc($dbvalue)
);
}
else {
@ -142,7 +151,6 @@ class PConfig {
dbesc($family),
dbesc($key)
);
}
// keep a separate copy for all variables which were
@ -178,7 +186,6 @@ class PConfig {
* The configuration key to delete
* @return mixed
*/
static public function Delete($uid, $family, $key) {
if(is_null($uid) || $uid === false)
@ -186,12 +193,12 @@ class PConfig {
$ret = false;
if(array_key_exists($uid,\App::$config)
&& is_array(\App::$config['uid'])
&& array_key_exists($family,\App::$config['uid'])
if(array_key_exists($uid,\App::$config)
&& is_array(\App::$config['uid'])
&& array_key_exists($family,\App::$config['uid'])
&& array_key_exists($key, \App::$config[$uid][$family]))
unset(\App::$config[$uid][$family][$key]);
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
intval($uid),
dbesc($family),
@ -202,4 +209,3 @@ class PConfig {
}
}

View file

@ -2,8 +2,11 @@
namespace Zotlabs\Lib;
// account configuration storage is built on top of the under-utilised xconfig
/**
* @brief Account configuration storage is built on top of the under-utilised xconfig.
*
* @see XConfig
*/
class SConfig {
static public function Load($server_id) {

View file

@ -2,7 +2,26 @@
namespace Zotlabs\Lib;
/**
* @brief Class for handling observer's config.
*
* <b>XConfig</b> is comparable to <i>PConfig</i>, except that it uses <i>xchan</i>
* (an observer hash) as an identifier.
*
* <b>XConfig</b> is used for observer specific configurations and takes a
* <i>xchan</i> as identifier.
* The storage is of size MEDIUMTEXT.
*
* @code{.php}$var = Zotlabs\Lib\XConfig::Get('xchan', 'category', 'key');
* // with default value for non existent key
* $var = Zotlabs\Lib\XConfig::Get('xchan', 'category', 'unsetkey', 'defaultvalue');@endcode
*
* The old (deprecated?) way to access a XConfig value is:
* @code{.php}$observer = App::get_observer_hash();
* if ($observer) {
* $var = get_xconfig($observer, 'category', 'key');
* }@endcode
*/
class XConfig {
/**
@ -15,7 +34,6 @@ class XConfig {
* The observer's hash
* @return void|false Returns false if xchan is not set
*/
static public function Load($xchan) {
if(! $xchan)
@ -56,9 +74,9 @@ class XConfig {
* The category of the configuration value
* @param string $key
* The configuration key to query
* @param boolean $default (optional) default false
* @return mixed Stored $value or false if it does not exist
*/
static public function Get($xchan, $family, $key, $default = false) {
if(! $xchan)
@ -70,7 +88,7 @@ class XConfig {
if((! array_key_exists($family, \App::$config[$xchan])) || (! array_key_exists($key, \App::$config[$xchan][$family])))
return $default;
return ((! is_array(\App::$config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$xchan][$family][$key]))
return ((! is_array(\App::$config[$xchan][$family][$key])) && (preg_match('|^a:[0-9]+:{.*}$|s', \App::$config[$xchan][$family][$key]))
? unserialize(\App::$config[$xchan][$family][$key])
: \App::$config[$xchan][$family][$key]
);
@ -82,7 +100,6 @@ class XConfig {
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the observer's $xchan hash.
*
*
* @param string $xchan
* The observer's hash
* @param string $family
@ -93,7 +110,6 @@ class XConfig {
* The value to store
* @return mixed Stored $value or false
*/
static public function Set($xchan, $family, $key, $value) {
// manage array value
@ -106,7 +122,7 @@ class XConfig {
if(! array_key_exists($family, \App::$config[$xchan]))
\App::$config[$xchan][$family] = array();
$ret = q("INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' ) ",
$ret = q("INSERT INTO xconfig ( xchan, cat, k, v ) VALUES ( '%s', '%s', '%s', '%s' )",
dbesc($xchan),
dbesc($family),
dbesc($key),
@ -126,6 +142,7 @@ class XConfig {
if($ret)
return $value;
return $ret;
}
@ -143,11 +160,11 @@ class XConfig {
* The configuration key to delete
* @return mixed
*/
static public function Delete($xchan, $family, $key) {
if(x(\App::$config[$xchan][$family], $key))
unset(\App::$config[$xchan][$family][$key]);
$ret = q("DELETE FROM xconfig WHERE xchan = '%s' AND cat = '%s' AND k = '%s'",
dbesc($xchan),
dbesc($family),

View file

@ -5,10 +5,20 @@ namespace Zotlabs\Render;
require_once('include/security.php');
require_once('include/menu.php');
/**
* @brief Comanche Page Description Language.
*
* Comanche is a markup language similar to bbcode with which to create elaborate
* and complex web pages by assembling them from a series of components - some of
* which are pre-built and others which can be defined on the fly. Comanche uses
* a Page Decription Language to create these pages.
*
* Comanche primarily chooses what content will appear in various regions of the
* page. The various regions have names and these names can change depending on
* what layout template you choose.
*/
class Comanche {
function parse($s, $pass = 0) {
$matches = array();
@ -18,13 +28,13 @@ class Comanche {
$s = str_replace($mtch[0], '', $s);
}
}
/*
* This section supports the "switch" statement of the form given by the following
* example. The [default][/default] block must be the last in the arbitrary
* This section supports the "switch" statement of the form given by the following
* example. The [default][/default] block must be the last in the arbitrary
* list of cases. The first case that matches the switch variable is used
* and the rest are not evaluated.
*
*
* [switch observer.language]
* [case de]
* [block]german-content[/block]
@ -37,7 +47,7 @@ class Comanche {
* [/default]
* [/switch]
*/
$cnt = preg_match_all("/\[switch (.*?)\](.*?)\[default\](.*?)\[\/default\]\s*\[\/switch\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
@ -60,7 +70,7 @@ class Comanche {
}
}
}
$cnt = preg_match_all("/\[if (.*?)\](.*?)\[else\](.*?)\[\/if\]/ism", $s, $matches, PREG_SET_ORDER);
if($cnt) {
foreach($matches as $mtch) {
@ -89,7 +99,6 @@ class Comanche {
$this->parse_pass0($s);
else
$this->parse_pass1($s);
}
function parse_pass0($s) {
@ -103,7 +112,7 @@ class Comanche {
$cnt = preg_match("/\[template=(.*?)\](.*?)\[\/template\]/ism", $s, $matches);
if($cnt) {
\App::$page['template'] = trim($matches[2]);
\App::$page['template_style'] = trim($matches[2]) . '_' . $matches[1];
\App::$page['template_style'] = trim($matches[2]) . '_' . $matches[1];
}
$cnt = preg_match("/\[template\](.*?)\[\/template\]/ism", $s, $matches);
@ -145,20 +154,23 @@ class Comanche {
}
/**
* Currently supported condition variables:
* @brief Replace conditional variables with real values.
*
* $config.xxx.yyy - get_config with cat = xxx and k = yyy
* $request - request uri for this page
* $observer.language - viewer's preferred language (closest match)
* $observer.address - xchan_addr or false
* $observer.name - xchan_name or false
* $observer - xchan_hash of observer or empty string
* $local_channel - logged in channel_id or false
* Currently supported condition variables:
* * $config.xxx.yyy - get_config with cat = xxx and k = yyy
* * $request - request uri for this page
* * $observer.language - viewer's preferred language (closest match)
* * $observer.address - xchan_addr or false
* * $observer.name - xchan_name or false
* * $observer - xchan_hash of observer or empty string
* * $local_channel - logged in channel_id or false
*
* @param string $v The conditional variable name
* @return string|boolean
*/
function get_condition_var($v) {
if($v) {
$x = explode('.',$v);
$x = explode('.', $v);
if($x[0] == 'config')
return get_config($x[1],$x[2]);
elseif($x[0] === 'request')
@ -179,6 +191,7 @@ class Comanche {
return $y['xchan_name'];
elseif($x[1] == 'webname')
return substr($y['xchan_addr'],0,strpos($y['xchan_addr'],'@'));
return false;
}
return get_observer_hash();
@ -186,30 +199,39 @@ class Comanche {
else
return false;
}
return false;
}
/**
* @brief Test for Conditional Execution conditions.
*
* This is extensible. The first version of variable testing supports tests of the forms:
*
* - [if $config.system.foo ~= baz] which will check if get_config('system','foo') contains the string 'baz';
* - [if $config.system.foo == baz] which will check if get_config('system','foo') is the string 'baz';
* - [if $config.system.foo != baz] which will check if get_config('system','foo') is not the string 'baz';
* - [if $config.system.foo >= 3] which will check if get_config('system','foo') is greater than or equal to 3;
* - [if $config.system.foo > 3] which will check if get_config('system','foo') is greater than 3;
* - [if $config.system.foo <= 3] which will check if get_config('system','foo') is less than or equal to 3;
* - [if $config.system.foo < 3] which will check if get_config('system','foo') is less than 3;
*
* - [if $config.system.foo {} baz] which will check if 'baz' is an array element in get_config('system','foo')
* - [if $config.system.foo {*} baz] which will check if 'baz' is an array key in get_config('system','foo')
* - [if $config.system.foo] which will check for a return of a true condition for get_config('system','foo');
*
* The values 0, '', an empty array, and an unset value will all evaluate to false.
*
* @param int|string $s
* @return boolean
*/
function test_condition($s) {
// This is extensible. The first version of variable testing supports tests of the forms:
// [if $config.system.foo ~= baz] which will check if get_config('system','foo') contains the string 'baz';
// [if $config.system.foo == baz] which will check if get_config('system','foo') is the string 'baz';
// [if $config.system.foo != baz] which will check if get_config('system','foo') is not the string 'baz';
// [if $config.system.foo >= 3] which will check if get_config('system','foo') is greater than or equal to 3;
// [if $config.system.foo > 3] which will check if get_config('system','foo') is greater than 3;
// [if $config.system.foo <= 3] which will check if get_config('system','foo') is less than or equal to 3;
// [if $config.system.foo < 3] which will check if get_config('system','foo') is less than 3;
// [if $config.system.foo {} baz] which will check if 'baz' is an array element in get_config('system','foo')
// [if $config.system.foo {*} baz] which will check if 'baz' is an array key in get_config('system','foo')
// [if $config.system.foo] which will check for a return of a true condition for get_config('system','foo');
// The values 0, '', an empty array, and an unset value will all evaluate to false.
if(preg_match('/[\$](.*?)\s\~\=\s(.*?)$/',$s,$matches)) {
$x = $this->get_condition_var($matches[1]);
if(stripos($x,trim($matches[2])) !== false)
return true;
return false;
}
@ -217,6 +239,7 @@ class Comanche {
$x = $this->get_condition_var($matches[1]);
if($x == trim($matches[2]))
return true;
return false;
}
@ -224,6 +247,7 @@ class Comanche {
$x = $this->get_condition_var($matches[1]);
if($x != trim($matches[2]))
return true;
return false;
}
@ -231,24 +255,31 @@ class Comanche {
$x = $this->get_condition_var($matches[1]);
if($x >= trim($matches[2]))
return true;
return false;
}
if(preg_match('/[\$](.*?)\s\<\=\s(.*?)$/',$s,$matches)) {
$x = $this->get_condition_var($matches[1]);
if($x <= trim($matches[2]))
return true;
return false;
}
if(preg_match('/[\$](.*?)\s\>\s(.*?)$/',$s,$matches)) {
$x = $this->get_condition_var($matches[1]);
if($x > trim($matches[2]))
return true;
return false;
}
if(preg_match('/[\$](.*?)\s\>\s(.*?)$/',$s,$matches)) {
$x = $this->get_condition_var($matches[1]);
if($x < trim($matches[2]))
return true;
return false;
}
@ -256,6 +287,7 @@ class Comanche {
$x = $this->get_condition_var($matches[1]);
if(is_array($x) && in_array(trim($matches[2]),$x))
return true;
return false;
}
@ -263,6 +295,7 @@ class Comanche {
$x = $this->get_condition_var($matches[1]);
if(is_array($x) && array_key_exists(trim($matches[2]),$x))
return true;
return false;
}
@ -270,13 +303,21 @@ class Comanche {
$x = $this->get_condition_var($matches[1]);
if($x)
return true;
return false;
}
return false;
return false;
}
/**
* @brief Return rendered menu for current channel_id.
*
* @see menu_render()
* @param string $s
* @param string $class (optional) default empty
* @return string
*/
function menu($s, $class = '') {
$channel_id = $this->get_channel_id();
@ -291,7 +332,7 @@ class Comanche {
}
if($channel_id) {
$m = menu_fetch($name,$channel_id, get_observer_hash());
$m = menu_fetch($name, $channel_id, get_observer_hash());
return menu_render($m, $class, $edit = false, $var);
}
}
@ -309,9 +350,8 @@ class Comanche {
* Returns the channel_id of the profile owner of the page, or the local_channel
* if there is no profile owner. Otherwise returns 0.
*
* @return channel_id
* @return int channel_id
*/
function get_channel_id() {
$channel_id = ((is_array(\App::$profile)) ? \App::$profile['profile_uid'] : 0);
@ -321,6 +361,13 @@ class Comanche {
return $channel_id;
}
/**
* @brief Returns a parsed block.
*
* @param string $s
* @param string $class (optional) default empty
* @return string parsed HTML of block
*/
function block($s, $class = '') {
$var = array();
$matches = array();
@ -339,7 +386,7 @@ class Comanche {
$channel_id = $this->get_channel_id();
if($channel_id) {
$r = q("select * from item inner join iconfig on iconfig.iid = item.id and item.uid = %d
$r = q("select * from item inner join iconfig on iconfig.iid = item.id and item.uid = %d
and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK' and iconfig.v = '%s' limit 1",
intval($channel_id),
dbesc($name)
@ -381,6 +428,12 @@ class Comanche {
return $o;
}
/**
* @brief Include JS depending on framework.
*
* @param string $s
* @return string
*/
function js($s) {
switch($s) {
@ -401,9 +454,14 @@ class Comanche {
$ret .= $init;
return $ret;
}
/**
* @brief Include CSS depending on framework.
*
* @param string $s
* @return string
*/
function css($s) {
switch($s) {
@ -418,17 +476,22 @@ class Comanche {
$ret = '<link rel="stylesheet" href="' . z_root() . '/' . $path . '" type="text/css" media="screen">';
return $ret;
}
// This doesn't really belong in Comanche, but it could also be argued that it is the perfect place.
// We need to be able to select what kind of template and decoration to use for the webpage at the heart of our content.
// For now we'll allow an '[authored]' element which defaults to name and date, or 'none' to remove these, and perhaps
// 'full' to provide a social network style profile photo.
// But leave it open to have richer templating options and perhaps ultimately discard this one, once we have a better idea
// of what template and webpage options we might desire.
function webpage(&$a,$s) {
/**
* This doesn't really belong in Comanche, but it could also be argued that it is the perfect place.
* We need to be able to select what kind of template and decoration to use for the webpage at the heart of our content.
* For now we'll allow an '[authored]' element which defaults to name and date, or 'none' to remove these, and perhaps
* 'full' to provide a social network style profile photo.
*
* But leave it open to have richer templating options and perhaps ultimately discard this one, once we have a better idea
* of what template and webpage options we might desire.
*
* @param[in,out] array $a
* @param string $s
* @return array
*/
function webpage(&$a, $s) {
$ret = array();
$matches = array();
@ -438,22 +501,20 @@ class Comanche {
$ret['authored'] = $mtch[1];
}
}
return $ret;
}
/**
* Render a widget
* @brief Render a widget.
*
* @param string $name
* @param string $text
*/
function widget($name, $text) {
$vars = array();
$matches = array();
$cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $text, $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
@ -480,7 +541,7 @@ class Comanche {
if(method_exists($x,$f)) {
return $x->$f($vars);
}
}
}
$func = 'widget_' . trim($name);
@ -563,9 +624,9 @@ class Comanche {
}
/*
* @function register_page_template($arr)
* Registers a page template/variant for use by Comanche selectors
/**
* @brief Registers a page template/variant for use by Comanche selectors.
*
* @param array $arr
* 'template' => template name
* 'variant' => array(
@ -577,8 +638,6 @@ class Comanche {
* )
* )
*/
function register_page_template($arr) {
\App::$page_layouts[$arr['template']] = array($arr['variant']);
return;

View file

@ -2,6 +2,8 @@
namespace Zotlabs\Web;
use Exception;
/**
*
* We have already parsed the server path into App::$argc and App::$argv
@ -34,7 +36,7 @@ class Router {
private $controller = null;
/**
* @brief Router constructor
* @brief Router constructor.
*
* @param[in,out] App &$a
* @throws Exception module not found
@ -98,15 +100,23 @@ class Router {
}
}
/*
* This provides a place for plugins to register module handlers which don't otherwise exist
* on the system, or to completely over-ride an existing module.
* If the plugin sets 'installed' to true we won't throw a 404 error for the specified module even if
* there is no specific module file or matching plugin name.
* The plugin should catch at least one of the module hooks for this URL.
$x = [
'module' => $module,
'installed' => \App::$module_loaded,
'controller' => $this->controller
];
/**
* @hooks module_loaded
* Called when a module has been successfully locate to server a URL request.
* This provides a place for plugins to register module handlers which don't otherwise exist
* on the system, or to completely over-ride an existing module.
* If the plugin sets 'installed' to true we won't throw a 404 error for the specified module even if
* there is no specific module file or matching plugin name.
* The plugin should catch at least one of the module hooks for this URL.
* * \e string \b module
* * \e boolean \b installed
* * \e mixed \b controller - The initialized module object
*/
$x = array('module' => $module, 'installed' => \App::$module_loaded, 'controller' => $this->controller);
call_hooks('module_loaded', $x);
if($x['installed']) {
\App::$module_loaded = true;
@ -131,14 +141,14 @@ class Router {
}
}
$x = [
'module' => $module,
'installed' => \App::$module_loaded,
$x = [
'module' => $module,
'installed' => \App::$module_loaded,
'controller' => $this->controller
];
call_hooks('page_not_found',$x);
// Stupid browser tried to pre-fetch our Javascript img template.
// Stupid browser tried to pre-fetch our Javascript img template.
// Don't log the event or return anything - just quietly exit.
if((x($_SERVER, 'QUERY_STRING')) && preg_match('/{[0-9]}/', $_SERVER['QUERY_STRING']) !== 0) {
@ -147,8 +157,8 @@ class Router {
if(get_config('system','log_404',true)) {
logger("Module {$module} not found.", LOGGER_DEBUG, LOG_WARNING);
logger('index.php: page not found: ' . $_SERVER['REQUEST_URI']
. ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: '
logger('index.php: page not found: ' . $_SERVER['REQUEST_URI']
. ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: '
. $_SERVER['QUERY_STRING'], LOGGER_DEBUG);
}

View file

@ -26,12 +26,11 @@ class Verify {
q("delete from verify where id = %d",
intval($r[0]['id'])
);
return true;
return true;
}
return false;
}
function get_meta($type,$channel_id,$token) {
$r = q("select id, meta from verify where vtype = '%s' and channel = %d and token = '%s' limit 1",
dbesc($type),
@ -42,12 +41,18 @@ class Verify {
q("delete from verify where id = %d",
intval($r[0]['id'])
);
return $r[0]['meta'];
return $r[0]['meta'];
}
return false;
}
function purge($type,$interval) {
/**
* @brief Purge entries of a verify-type older than interval.
*
* @param string $type Verify type
* @param string $interval SQL compatible time interval
*/
function purge($type, $interval) {
q("delete from verify where vtype = '%s' and created < %s - INTERVAL %s",
dbesc($type),
db_utcnow(),

215
boot.php
View file

@ -1,7 +1,8 @@
<?php
/** @file boot.php
/**
* @file boot.php
*
* This file defines some global constants and includes the central App class.
* @brief This file defines some global constants and includes the central App class.
*/
/**
@ -95,10 +96,9 @@ $DIRECTORY_FALLBACK_SERVERS = array(
* App::$config['system']['jpeg_quality'] = n;
* in .htconfig.php, where n is netween 1 and 100, and with very poor results
* below about 50
*
*/
define ( 'JPEG_QUALITY', 100 );
/**
* App::$config['system']['png_quality'] from 0 (uncompressed) to 9
*/
@ -107,7 +107,6 @@ define ( 'PNG_QUALITY', 8 );
/**
* Language detection parameters
*/
define ( 'LANGUAGE_DETECT_MIN_LENGTH', 128 );
define ( 'LANGUAGE_DETECT_MIN_CONFIDENCE', 0.01 );
@ -264,7 +263,6 @@ define ( 'NETWORK_LINKEDIN', 'lnkd'); // LinkedIn
define ( 'NETWORK_XMPP', 'xmpp'); // XMPP
define ( 'NETWORK_MYSPACE', 'mysp'); // MySpace
define ( 'NETWORK_GPLUS', 'goog'); // Google+
define ( 'NETWORK_PHANTOM', 'unkn'); // Place holder
@ -455,8 +453,8 @@ define ( 'NAMESPACE_STATUSNET', 'http://status.net/schema/api/1/' );
define ( 'NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom' );
define ( 'NAMESPACE_YMEDIA', 'http://search.yahoo.com/mrss/' );
// We should be using versioned jsonld contexts so that signatures will be slightly more reliable.
// Why signatures are unreliable by design is a problem nobody seems to care about
// We should be using versioned jsonld contexts so that signatures will be slightly more reliable.
// Why signatures are unreliable by design is a problem nobody seems to care about
// "because it's a proposed W3C standard". .
// Anyway, if you use versioned contexts, communication with Mastodon fails. Have not yet investigated
@ -642,7 +640,7 @@ function sys_boot() {
unset($db_host, $db_port, $db_user, $db_pass, $db_data, $db_type);
/**
/*
* Load configs from db. Overwrite configs from .htconfig.php
*/
@ -652,20 +650,21 @@ function sys_boot() {
App::$session = new Zotlabs\Web\Session();
App::$session->init();
load_hooks();
/**
* @hooks init_1
*/
call_hooks('init_1');
}
}
/**
* @brief Reverse the effect of magic_quotes_gpc if it is enabled.
*
* Reverse the effect of magic_quotes_gpc if it is enabled.
* Please disable magic_quotes_gpc so we don't have to do this.
* See http://php.net/manual/en/security.magicquotes.disabling.php
*
*/
function startup() {
error_reporting(E_ERROR | E_WARNING | E_PARSE);
@ -709,20 +708,18 @@ function startup() {
* which is now static (although currently constructed at startup). We are only converting
* 'system' config settings.
*/
class miniApp {
public $config = array('system' => array());
public function convert() {
if($this->config['system']) {
foreach($this->config['system'] as $k => $v)
App::$config['system'][$k] = $v;
foreach($this->config['system'] as $k => $v)
App::$config['system'][$k] = $v;
}
}
}
/**
* class: App
*
@ -886,11 +883,11 @@ class App {
if(x($_SERVER,'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443)
self::$hostname .= ':' . $_SERVER['SERVER_PORT'];
/**
/*
* Figure out if we are running at the top of a domain
* or in a sub-directory and adjust accordingly
*/
$path = trim(dirname($_SERVER['SCRIPT_NAME']),'/\\');
if(isset($path) && strlen($path) && ($path != self::$path))
self::$path = $path;
@ -922,7 +919,7 @@ class App {
*
* There will always be one argument. If provided a naked domain
* URL, self::$argv[0] is set to "home".
*
*
* If $argv[0] has a period in it, for example foo.json; rewrite
* to module = 'foo' and set $_REQUEST['module_format'] = 'json';
*/
@ -1147,7 +1144,12 @@ class App {
head_add_link(['rel' => 'shortcut icon', 'href' => head_get_icon()]);
$x = [ 'header' => '' ];
call_hooks('build_pagehead',$x);
/**
* @hooks build_pagehead
* Called when creating the HTML page header.
* * \e string \b header - Return the HTML header which should be added
*/
call_hooks('build_pagehead', $x);
/* put the head template at the beginning of page['htmlhead']
* since the code added by the modules frequently depends on it
@ -1178,8 +1180,10 @@ class App {
}
/**
* register template engine class
* if $name is "", is used class static property $class::$name
* @brief Register template engine class.
*
* If $name is "", is used class static property $class::$name.
*
* @param string $class
* @param string $name
*/
@ -1198,8 +1202,9 @@ class App {
}
/**
* return template engine instance. If $name is not defined,
* return engine defined by theme, or default
* @brief Return template engine instance.
*
* If $name is not defined, return engine defined by theme, or default.
*
* @param string $name Template engine name
*
@ -1302,8 +1307,11 @@ function x($s, $k = null) {
}
// called from db initialisation if db is dead.
/**
* @brief Called from db initialisation if db is dead.
*
* @ref include/system_unavailable.php will handle everything further.
*/
function system_unavailable() {
include('include/system_unavailable.php');
system_down();
@ -1359,7 +1367,12 @@ function os_mkdir($path, $mode = 0777, $recursive = false) {
}
// recursively delete a directory
/**
* @brief Recursively delete a directory.
*
* @param string $path
* @return boolean
*/
function rrmdir($path) {
if(is_dir($path) === true) {
$files = array_diff(scandir($path), array('.', '..'));
@ -1386,10 +1399,11 @@ function is_ajax() {
}
// Primarily involved with database upgrade, but also sets the
// base url for use in cmdline programs which don't have
// $_SERVER variables, and synchronising the state of installed plugins.
/**
* Primarily involved with database upgrade, but also sets the
* base url for use in cmdline programs which don't have
* $_SERVER variables, and synchronising the state of installed plugins.
*/
function check_config() {
$saved = get_config('system','urlverify');
@ -1600,15 +1614,23 @@ function fix_system_urls($oldurl, $newurl) {
);
}
}
}
// wrapper for adding a login box. If $register == true provide a registration
// link. This will most always depend on the value of App::$config['system']['register_policy'].
// returns the complete html for inserting into the page
function login($register = false, $form_id = 'main-login', $hiddens=false, $login_page = true) {
/**
* @brief Wrapper for adding a login box.
*
* If $register == true provide a registration link. This will most always depend
* on the value of App::$config['system']['register_policy'].
* Returns the complete html for inserting into the page
*
* @param boolean $register (optional) default false
* @param string $form_id (optional) default \e main-login
* @param boolean $hiddens (optional) default false
* @param boolean $login_page (optional) default true
* @return string Parsed HTML code.
*/
function login($register = false, $form_id = 'main-login', $hiddens = false, $login_page = true) {
$o = '';
$reg = false;
$reglink = get_config('system', 'register_link');
@ -1648,6 +1670,11 @@ function login($register = false, $form_id = 'main-login', $hiddens=false, $logi
'$lostlink' => t('Password Reset'),
));
/**
* @hooks login_hook
* Called when generating the login form.
* * \e string with parsed HTML
*/
call_hooks('login_hook', $o);
return $o;
@ -1736,9 +1763,13 @@ function remote_channel() {
}
/**
* @brief Show an error or alert text on next page load.
*
* Contents of $s are displayed prominently on the page the next time
* a page is loaded. Usually used for errors or alerts.
*
* For informational text use info().
*
* @param string $s Text to display
*/
function notice($s) {
@ -1751,18 +1782,20 @@ function notice($s) {
// - typically seen as multiple 'permission denied' messages
// as a result of auto-reloading a protected page with &JS=1
if(in_array($s,$_SESSION['sysmsg']))
if(in_array($s, $_SESSION['sysmsg']))
return;
if(App::$interactive) {
$_SESSION['sysmsg'][] = $s;
}
}
/**
* @brief Show an information text on next page load.
*
* Contents of $s are displayed prominently on the page the next time a page is
* loaded. Usually used for information.
*
* For error and alerts use notice().
*
* @param string $s Text to display
@ -1777,7 +1810,7 @@ function info($s) {
}
/**
* @brief Wrapper around config to limit the text length of an incoming message
* @brief Wrapper around config to limit the text length of an incoming message.
*
* @return int
*/
@ -1787,15 +1820,15 @@ function get_max_import_size() {
/**
*
* Wrap calls to proc_close(proc_open()) and call hook
* @brief Wrap calls to proc_close(proc_open()) and call hook
* so plugins can take part in process :)
*
* args:
* $cmd program to run
* next args are passed as $cmd command line
*
* e.g.: proc_run("ls","-la","/tmp");
* e.g.:
* @code{.php}proc_run("ls", "-la", "/tmp");@endcode
*
* $cmd and string args are surrounded with ""
*/
@ -1810,8 +1843,16 @@ function proc_run(){
$args = flatten_array_recursive($args);
$arr = array('args' => $args, 'run_cmd' => true);
$arr = [
'args' => $args,
'run_cmd' => true
];
/**
* @hooks proc_run
* Called when invoking PHP sub processes.
* * \e array \b args
* * \e boolean \b run_cmd
*/
call_hooks('proc_run', $arr);
if(! $arr['run_cmd'])
@ -1873,7 +1914,6 @@ function is_windows() {
*
* @return bool true if user is an admin
*/
function is_site_admin() {
if(! session_id())
@ -1943,7 +1983,6 @@ function load_contact_links($uid) {
*
* @return string
*/
function build_querystring($params, $name = null) {
$ret = '';
foreach($params as $key => $val) {
@ -1962,12 +2001,14 @@ function build_querystring($params, $name = null) {
}
}
}
return $ret;
}
// much better way of dealing with c-style args
/*
* @brief Much better way of dealing with c-style args.
*/
function argc() {
return App::$argc;
}
@ -1986,9 +2027,8 @@ function dba_timer() {
/**
* @brief Returns xchan_hash from the observer.
*
* @return empty string if no observer, otherwise xchan_hash from observer
* @return string xchan_hash from observer, otherwise empty string if no observer
*/
function get_observer_hash() {
$observer = App::get_observer();
if(is_array($observer))
@ -1999,19 +2039,24 @@ function get_observer_hash() {
/**
* 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
*
* Taken from http://webcheatsheet.com/php/get_current_page_url.php
*
* @return string
*/
function curPageURL() {
$pageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
if ($_SERVER["HTTPS"] == "on") {
$pageURL .= "s";
}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80" && $_SERVER["SERVER_PORT"] != "443") {
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
return $pageURL;
}
@ -2022,7 +2067,6 @@ function curPageURL() {
*
* @todo not fully implemented yet
*
* @param App $a global application object
* @param string $navname
*
* @return mixed
@ -2046,8 +2090,17 @@ function load_pdl() {
if (! count(App::$layout)) {
$arr = array('module' => App::$module, 'layout' => '');
call_hooks('load_pdl',$arr);
$arr = [
'module' => App::$module,
'layout' => ''
];
/**
* @hooks load_pdl
* Called when we load a PDL file or description.
* * \e string \b module
* * \e string \b layout
*/
call_hooks('load_pdl', $arr);
$layout = $arr['layout'];
$n = 'mod_' . App::$module . '.pdl' ;
@ -2096,7 +2149,7 @@ function construct_page() {
if($uid) {
$navbar = get_pconfig($uid,'system','navbar',$navbar);
}
if($comanche && App::$layout['navbar']) {
$navbar = App::$layout['navbar'];
}
@ -2150,7 +2203,17 @@ function construct_page() {
// layout completely with a new layout definition, or replace/remove existing content.
if($comanche) {
$arr = array('module' => App::$module, 'layout' => App::$layout);
$arr = [
'module' => App::$module,
'layout' => App::$layout
];
/**
* @hooks construct_page
* General purpose hook to provide content to certain page regions.
* Called when constructing the Comanche page.
* * \e string \b module
* * \e string \b layout
*/
call_hooks('construct_page', $arr);
App::$layout = $arr['layout'];
@ -2294,10 +2357,13 @@ function get_directory_primary() {
/**
* @brief return relative date of last completed poller execution.
* @brief Return relative date of last completed poller execution.
*
* @return string relative date of last completed poller execution
*/
function get_poller_runtime() {
$t = get_config('system', 'lastpoll');
return relative_date($t);
}
@ -2307,6 +2373,7 @@ function z_get_upload_dir() {
$upload_dir = ini_get('upload_tmp_dir');
if(! $upload_dir)
$upload_dir = sys_get_temp_dir();
return $upload_dir;
}
@ -2314,16 +2381,22 @@ function z_get_temp_dir() {
$temp_dir = get_config('system','tempdir');
if(! $temp_dir)
$temp_dir = sys_get_temp_dir();
return $upload_dir;
}
function z_check_cert() {
if(strpos(z_root(),'https://') !== false) {
/**
* @brief Check if server certificate is valid.
*
* Notify admin if not.
*/
function z_check_cert() {
if(strpos(z_root(), 'https://') !== false) {
$x = z_fetch_url(z_root() . '/siteinfo.json');
if(! $x['success']) {
$recurse = 0;
$y = z_fetch_url(z_root() . '/siteinfo.json',false,$recurse,array('novalidate' => true));
$y = z_fetch_url(z_root() . '/siteinfo.json', false, $recurse, ['novalidate' => true]);
if($y['success'])
cert_bad_email();
}
@ -2336,7 +2409,6 @@ function z_check_cert() {
*
* If a hub is available over https it must have a publicly valid certificate.
*/
function cert_bad_email() {
return z_mail(
[
@ -2345,7 +2417,7 @@ function cert_bad_email() {
'textVersion' => replace_macros(get_intltext_template('cert_bad_eml.tpl'),
[
'$sitename' => App::$config['system']['sitename'],
'$siteurl' => z_root(),
'$siteurl' => z_root(),
'$error' => t('Website SSL certificate is not valid. Please correct.')
]
)
@ -2407,7 +2479,6 @@ function check_for_new_perms() {
\Zotlabs\Access\PermissionLimits::Set($cc['channel_id'],$p,0);
}
$set = ((array_key_exists('perms_connect',$rp) && in_array($p,$rp['perms_connect'])) ? 1 : 0);
// foreach connection set to the perms_connect value
if($x) {
@ -2426,11 +2497,9 @@ function check_for_new_perms() {
// We should probably call perms_refresh here, but this should get pushed in 24 hours and there is no urgency
if($found_new_perm)
set_config('system','perms',$pcurrent);
}
/**
* @brief Send warnings every 3-5 days if cron is not running.
*/
@ -2479,11 +2548,15 @@ function check_cron_broken() {
}
/**
* @brief
*
* @param boolean $allow_account (optional) default false
* @return boolean
*/
function observer_prohibited($allow_account = false) {
if($allow_account)
return (((get_config('system','block_public')) && (! get_account_id()) && (! remote_channel())) ? true : false );
return (((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) ? true : false );
return (((get_config('system', 'block_public')) && (! get_account_id()) && (! remote_channel())) ? true : false );
return (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false );
}

View file

@ -110,7 +110,7 @@ function fixacl(&$item) {
*
* @param array $defaults Optional access control list for the initial state of the dialog.
* @param boolean $show_jotnets Whether plugins for federated networks should be included in the permissions dialog
* @param PermissionDescription $emptyACL_description - An optional description for the permission implied by selecting an empty ACL. Preferably an instance of PermissionDescription.
* @param \Zotlabs\Lib\PermissionDescription $emptyACL_description - An optional description for the permission implied by selecting an empty ACL. Preferably an instance of PermissionDescription.
* @param string $dialog_description Optional message to include at the top of the dialog. E.g. "Warning: Post permissions cannot be changed once sent".
* @param string $context_help Allows the dialog to present a help icon. E.g. "acl_dialog_post"
* @param boolean $readonly Not implemented yet. When implemented, the dialog will use acl_readonly.tpl instead, so that permissions may be viewed for posts that can no longer have their permissions changed.
@ -172,7 +172,7 @@ function populate_acl($defaults = null,$show_jotnets = true, $emptyACL_descripti
if(count($allow_cid) === 1 && $channel && $allow_cid[0] = $channel['channel_hash'] && (! $allow_gid) && (! $deny_gid) && (! $deny_cid)) {
$just_me = true;
$custom = false;
}
}
$r = q("SELECT id, profile_guid, profile_name from profile where is_default = 0 and uid = %d order by profile_name",
intval(local_channel())

View file

@ -21,7 +21,7 @@ require_once('include/group.php');
* This function takes a file name and guess the mimetype from the
* filename extension.
*
* @param $filename a string filename
* @param string $filename a string filename
* @return string The mimetype according to a file ending.
*/
function z_mime_content_type($filename) {
@ -412,6 +412,10 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
require_once('include/photos.php');
/**
* @hooks photo_upload_begin
* Called when attempting to upload a photo.
*/
call_hooks('photo_upload_begin', $arr);
$ret = array('success' => false);
@ -486,14 +490,36 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
$x = attach_mkdir($channel,$observer_hash,$arr);
if($x['message'])
logger('import_directory: ' . $x['message']);
return;
}
}
elseif($options !== 'update') {
$f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => '');
$f = [
'src' => '',
'filename' => '',
'filesize' => 0,
'type' => ''
];
call_hooks('photo_upload_file',$f);
call_hooks('attach_upload_file',$f);
/**
* @hooks photo_upload_file
* Called to generate alternate filenames for an upload.
* * \e string \b src - return value, default empty
* * \e string \b filename - return value, default empty
* * \e number \b filesize - return value, default 0
* * \e string \b type - return value, default empty
*/
call_hooks('photo_upload_file', $f);
/**
* @hooks attach_upload_file
* Called when uploading a file.
* * \e string \b src - return value, default empty
* * \e string \b filename - return value, default empty
* * \e number \b filesize - return value, default 0
* * \e string \b type - return value, default empty
*/
call_hooks('attach_upload_file', $f);
if (x($f,'src') && x($f,'filesize')) {
$src = $f['src'];
@ -680,7 +706,13 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
$ret['message'] = sprintf( t('File exceeds size limit of %d'), $maxfilesize);
if($remove_when_processed)
@unlink($src);
call_hooks('photo_upload_end',$ret);
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
*/
call_hooks('photo_upload_end', $ret);
return $ret;
}
@ -695,7 +727,12 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
if($remove_when_processed)
@unlink($src);
call_hooks('photo_upload_end',$ret);
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
*/
call_hooks('photo_upload_end', $ret);
return $ret;
}
}
@ -773,7 +810,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
);
}
elseif($options === 'update') {
$r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', edited = '%s', os_storage = %d, is_photo = %d, os_path = '%s',
$r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', edited = '%s', os_storage = %d, is_photo = %d, os_path = '%s',
display_path = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where id = %d and uid = %d",
dbesc((array_key_exists('filename',$arr)) ? $arr['filename'] : $x[0]['filename']),
dbesc((array_key_exists('filetype',$arr)) ? $arr['filetype'] : $x[0]['filetype']),
@ -862,7 +899,13 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
if(! $r) {
$ret['message'] = t('File upload failed. Possible system limit or action terminated.');
call_hooks('photo_upload_end',$ret);
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
*/
call_hooks('photo_upload_end', $ret);
return $ret;
}
@ -875,15 +918,25 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
if(! $r) {
$ret['message'] = t('Stored file could not be verified. Upload failed.');
call_hooks('photo_upload_end',$ret);
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
*/
call_hooks('photo_upload_end', $ret);
return $ret;
}
$ret['success'] = true;
$ret['data'] = $r[0];
if(! $is_photo) {
// This would've been called already with a success result in photos_upload() if it was a photo.
call_hooks('photo_upload_end',$ret);
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
* This would've been called already with a success result in photos_upload() if it was a photo.
*/
call_hooks('photo_upload_end', $ret);
}
if($dosync) {
@ -986,7 +1039,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) {
$os_basepath = 'store/' . $channel['channel_address'];
logger('attach_mkdir: basepath: ' . $os_basepath);
logger('basepath: ' . $os_basepath);
if(! is_dir($os_basepath))
os_mkdir($os_basepath,STORAGE_DEFAULT_PERMISSIONS, true);
@ -1055,7 +1108,7 @@ function attach_mkdir($channel, $observer_hash, $arr = null) {
return $ret;
}
$dpath = $r[0]['filename'] . (($dpath) ? '/' . $dpath : '');
$dpath = $r[0]['filename'] . (($dpath) ? '/' . $dpath : '');
if($lfile)
$lpath = $r[0]['hash'] . (($lpath) ? '/' . $lpath : '');
@ -1154,7 +1207,7 @@ function attach_mkdirp($channel, $observer_hash, $arr = null) {
$basepath = 'store/' . $channel['channel_address'];
logger('attach_mkdirp: basepath: ' . $basepath);
logger('basepath: ' . $basepath);
if(! is_dir($basepath))
os_mkdir($basepath,STORAGE_DEFAULT_PERMISSIONS, true);
@ -1180,6 +1233,7 @@ function attach_mkdirp($channel, $observer_hash, $arr = null) {
foreach($paths as $p) {
if(! $p)
continue;
$arx = array(
'filename' => $p,
'folder' => $current_parent,
@ -1308,7 +1362,7 @@ function attach_delete($channel_id, $resource, $is_photo = 0) {
);
if(! $r) {
attach_drop_photo($channel_id,$resource);
attach_drop_photo($channel_id,$resource);
return;
}
@ -1501,6 +1555,13 @@ function find_folder_hash_by_attach_hash($channel_id, $attachHash, $recurse = fa
return $hash;
}
/**
* @brief Return the hash of an attachment's folder.
*
* @param int $channel_id
* @param string $path
* @return string
*/
function find_folder_hash_by_path($channel_id, $path) {
if(! $path)
@ -1530,7 +1591,6 @@ function find_folder_hash_by_path($channel_id, $path) {
return '';
return $parent_hash;
}
/**
@ -1557,9 +1617,11 @@ function find_filename_by_hash($channel_id, $attachHash) {
}
/**
* @brief Pipes $in to $out in 16MB chunks.
*
* @param $in
* @param $out
* @param resource $in File pointer of input
* @param resource $out File pointer of output
* @return number with the size
*/
function pipe_streams($in, $out) {
$size = 0;
@ -1726,11 +1788,12 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid,
}
/**
* @brief Create file activity object
* @brief Create file activity object.
*
* @param int $channel_id
* @param string $hash
* @param string $cloudpath
* @param string $url
* @return array An associative array for the specified file.
*/
function get_file_activity_object($channel_id, $hash, $url) {
@ -2257,7 +2320,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash) {
if($r[0]['is_photo']) {
$t = q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s'
$t = q("update photo set album = '%s', filename = '%s', os_path = '%s', display_path = '%s'
where resource_id = '%s' and uid = %d",
dbesc($newdirname),
dbesc($filename),
@ -2349,8 +2412,6 @@ function attach_syspaths($channel_id,$attach_hash) {
while($attach_hash);
return [ 'os_path' => $os_path, 'path' => $path ];
}
@ -2386,7 +2447,7 @@ function save_chunk($channel,$start,$end,$len) {
$tmp_path = $_FILES['files']['tmp_name'];
$new_base = 'store/[data]/' . $channel['channel_address'] . '/tmp';
os_mkdir($new_base,STORAGE_DEFAULT_PERMISSIONS,true);
$new_path = $new_base . '/' . $_FILES['files']['name'];
if(! file_exists($new_path)) {
@ -2417,20 +2478,19 @@ function save_chunk($channel,$start,$end,$len) {
}
/*
* chunkloader
* Submit handler for chunked uploads
*
/**
* @brief Submit handler for chunked uploads.
*
* @param array $channel
* @param array $arr
* @return array
*/
function chunkloader($channel,$arr) {
function chunkloader($channel, $arr) {
logger('request: ' . print_r($arr,true), LOGGER_DEBUG);
logger('files: ' . print_r($_FILES,true), LOGGER_DEBUG);
$result = [];
$tmp_path = $_FILES['file']['tmp_name'];
$new_base = 'store/[data]/' . $channel['channel_address'] . '/tmp';
@ -2439,7 +2499,7 @@ function chunkloader($channel,$arr) {
$new_path = $new_base . '/' . $arr['resumableFilename'];
rename($tmp_path,$new_path . '.' . intval($arr['resumableChunkNumber']));
$missing_parts = false;
for($x = 1; $x <= intval($arr['resumableTotalChunks']); $x ++) {
if(! file_exists($new_path . '.' . $x)) {
@ -2475,7 +2535,7 @@ function chunkloader($channel,$arr) {
$result['error'] = 0;
$result['size'] = $arr['resumableTotalSize'];
$result['complete'] = true;
return $result;
return $result;
}

View file

@ -1,6 +1,7 @@
<?php
/**
* @file include/channel.php
* @brief Channel related functions.
*/
require_once('include/zot.php');
@ -58,10 +59,8 @@ function identity_check_service_class($account_id) {
* Plugins can set additional policies such as full name requirements, character
* sets, multi-byte length, etc.
*
* @hooks validate_channelname
* * \e array \b name
* @param string $name
* @returns nil return if name is valid, or string describing the error state.
* @return string describing the error state, or nil return if name is valid
*/
function validate_channelname($name) {
@ -72,6 +71,12 @@ function validate_channelname($name) {
return t('Name too long');
$arr = ['name' => $name];
/**
* @hooks validate_channelname
* Used to validate the names used by a channel.
* * \e string \b name
* * \e string \b message - return error message
*/
call_hooks('validate_channelname', $arr);
if (x($arr, 'message'))
@ -259,7 +264,6 @@ function create_identity($arr) {
'channel_system' => intval($system),
'channel_expire_days' => intval($expire),
'channel_timezone' => App::$timezone
]
);
@ -280,9 +284,19 @@ function create_identity($arr) {
$photo_type = null;
$z = [ 'account' => $a[0], 'channel' => $r[0], 'photo_url' => '' ];
call_hooks('create_channel_photo',$z);
$z = [
'account' => $a[0],
'channel' => $r[0],
'photo_url' => ''
];
/**
* @hooks create_channel_photo
* * \e array \b account
* * \e array \b channel
* * \e string \b photo_url - Return value
*/
call_hooks('create_channel_photo', $z);
if($z['photo_url']) {
$photo_type = import_channel_photo_from_url($z['photo_url'],$arr['account_id'],$r[0]['channel_id']);
}
@ -322,7 +336,7 @@ function create_identity($arr) {
]
);
if(! $r)
logger('create_identity: Unable to store hub location');
logger('Unable to store hub location');
$newuid = $ret['channel']['channel_id'];
@ -454,12 +468,18 @@ function create_identity($arr) {
require_once('include/follow.php');
if(! is_array($accts))
$accts = array($accts);
foreach($accts as $acct) {
if(trim($acct))
new_contact($newuid,trim($acct),$ret['channel'],false);
}
}
/**
* @hooks create_identity
* Called when creating a channel.
* * \e int - The UID of the created identity
*/
call_hooks('create_identity', $newuid);
Zotlabs\Daemon\Master::Summon(array('Directory', $ret['channel']['channel_id']));
@ -576,14 +596,14 @@ function channel_change_address($channel,$new_address) {
$old_address = $channel['channel_address'];
if($new_address === 'sys') {
$ret['message'] = t('Reserved nickname. Please choose another.');
return $ret;
}
$ret['message'] = t('Reserved nickname. Please choose another.');
return $ret;
}
if(check_webbie(array($new_address)) !== $new_address) {
$ret['message'] = t('Nickname has unsupported characters or is already being used on this site.');
return $ret;
}
if(check_webbie(array($new_address)) !== $new_address) {
$ret['message'] = t('Nickname has unsupported characters or is already being used on this site.');
return $ret;
}
$r = q("update channel set channel_address = '%s' where channel_id = %d",
dbesc($new_address),
@ -644,7 +664,7 @@ function channel_change_address($channel,$new_address) {
);
}
}
}
}
Zotlabs\Daemon\Master::Summon(array('Notifier', 'refresh_all', $channel['channel_id']));
@ -653,10 +673,6 @@ function channel_change_address($channel,$new_address) {
}
/**
* @brief Set default channel to be used on login.
*
@ -664,9 +680,9 @@ function channel_change_address($channel,$new_address) {
* login account
* @param int $channel_id
* channel id to set as default for this account
* @param boolean $force
* if true, set this default unconditionally
* if $force is false only do this if there is no existing default
* @param boolean $force (optional) default true
* - if true, set this default unconditionally
* - if $force is false only do this if there is no existing default
*/
function set_default_login_identity($account_id, $channel_id, $force = true) {
$r = q("select account_default_channel from account where account_id = %d limit 1",
@ -685,8 +701,6 @@ function set_default_login_identity($account_id, $channel_id, $force = true) {
/**
* @brief Return an array with default list of sections to export.
*
* @hooks get_default_export_sections
* * \e array \b sections
* @return array with default section names to export
*/
function get_default_export_sections() {
@ -703,6 +717,11 @@ function get_default_export_sections() {
];
$cb = [ 'sections' => $sections ];
/**
* @hooks get_default_export_sections
* Called to get the default list of functional data groups to export in identity_basic_export().
* * \e array \b sections - return value
*/
call_hooks('get_default_export_sections', $cb);
return $cb['sections'];
@ -714,15 +733,11 @@ function get_default_export_sections() {
* which would be necessary to create a nomadic identity clone. This includes
* most channel resources and connection information with the exception of content.
*
* @hooks identity_basic_export
* * \e int \b channel_id
* * \e array \b sections
* * \e array \b data
* @param int $channel_id
* Channel_id to export
* @param array $sections (optional)
* Which sections to include in the export, default see get_default_export_sections()
* @returns array
* @return array
* See function for details
*/
function identity_basic_export($channel_id, $sections = null) {
@ -967,7 +982,7 @@ function identity_basic_export($channel_id, $sections = null) {
}
}
if(in_array('items',$sections)) {
if(in_array('items', $sections)) {
/** @warning this may run into memory limits on smaller systems */
/** export three months of posts. If you want to export and import all posts you have to start with
@ -991,22 +1006,42 @@ function identity_basic_export($channel_id, $sections = null) {
}
}
$addon = [ 'channel_id' => $channel_id, 'sections' => $sections, 'data' => $ret];
call_hooks('identity_basic_export',$addon);
$addon = [
'channel_id' => $channel_id,
'sections' => $sections,
'data' => $ret
];
/**
* @hooks identity_basic_export
* Called when exporting a channel's basic information for backup or transfer.
* * \e number \b channel_id - The channel ID
* * \e array \b sections
* * \e array \b data - The data will get returned
*/
call_hooks('identity_basic_export', $addon);
$ret = $addon['data'];
return $ret;
}
function identity_export_year($channel_id,$year,$month = 0) {
/**
* @brief Export items for a year, or a month of a year.
*
* @param int $channel_id The channel ID
* @param number $year YYYY
* @param number $month (optional) 0-12, default 0 complete year
* @return array An associative array
* * \e array \b relocate - (optional)
* * \e array \b item - array with items encoded_item()
*/
function identity_export_year($channel_id, $year, $month = 0) {
if(! $year)
return array();
if($month && $month <= 12) {
$target_month = sprintf('%02d',$month);
$target_month_plus = sprintf('%02d',$month+1);
$target_month = sprintf('%02d', $month);
$target_month_plus = sprintf('%02d', $month+1);
}
else
$target_month = '01';
@ -1017,13 +1052,13 @@ function identity_export_year($channel_id,$year,$month = 0) {
if($ch) {
$ret['relocate'] = [ 'channel_address' => $ch['channel_address'], 'url' => z_root()];
}
$mindate = datetime_convert('UTC','UTC',$year . '-' . $target_month . '-01 00:00:00');
$mindate = datetime_convert('UTC', 'UTC', $year . '-' . $target_month . '-01 00:00:00');
if($month && $month < 12)
$maxdate = datetime_convert('UTC','UTC',$year . '-' . $target_month_plus . '-01 00:00:00');
$maxdate = datetime_convert('UTC', 'UTC', $year . '-' . $target_month_plus . '-01 00:00:00');
else
$maxdate = datetime_convert('UTC','UTC',$year+1 . '-01-01 00:00:00');
$maxdate = datetime_convert('UTC', 'UTC', $year+1 . '-01-01 00:00:00');
$r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created",
$r = q("select * from item where ( item_wall = 1 or item_type != %d ) and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created",
intval(ITEM_TYPE_POST),
intval($channel_id),
dbesc($mindate),
@ -1033,9 +1068,9 @@ function identity_export_year($channel_id,$year,$month = 0) {
if($r) {
$ret['item'] = array();
xchan_query($r);
$r = fetch_post_tags($r,true);
$r = fetch_post_tags($r, true);
foreach($r as $rr)
$ret['item'][] = encode_item($rr,true);
$ret['item'][] = encode_item($rr, true);
}
return $ret;
@ -1274,6 +1309,7 @@ function profile_edit_menu($uid) {
foreach($r as $rr) {
if(!($multi_profiles || $rr['is_default']))
continue;
$ret['menu']['entries'][] = array(
'photo' => $rr['thumb'],
'id' => $rr['id'],
@ -1298,8 +1334,8 @@ function profile_edit_menu($uid) {
*
* @param array $profile
* @param int $block
* @param boolean $show_connect
* @param mixed $zcard
* @param boolean $show_connect (optional) default true
* @param mixed $zcard (optional) default false
*
* @return HTML string suitable for sidebar inclusion
* Exceptions: Returns empty string if passed $profile is wrong type or not populated
@ -1327,6 +1363,10 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
$profile['picdate'] = urlencode($profile['picdate']);
/**
* @hooks profile_sidebar_enter
* Called before generating the 'channel sidebar' or mini-profile.
*/
call_hooks('profile_sidebar_enter', $profile);
if($show_connect) {
@ -1409,22 +1449,30 @@ function profile_sidebar($profile, $block = 0, $show_connect = true, $zcard = fa
'$reddress' => $reddress,
'$rating' => '',
'$contact_block' => $contact_block,
'$editmenu' => profile_edit_menu($profile['uid'])
'$editmenu' => profile_edit_menu($profile['uid'])
));
$arr = array('profile' => $profile, 'entry' => $o);
$arr = [
'profile' => $profile,
'entry' => $o
];
/**
* @hooks profile_sidebar
* Called when generating the 'channel sidebar' or mini-profile.
* * \e array \b profile
* * \e string \b entry - The parsed HTML template
*/
call_hooks('profile_sidebar', $arr);
return $arr['entry'];
}
function gender_icon($gender) {
// logger('gender: ' . $gender);
// This can easily get throw off if the observer language is different
// This can easily get throw off if the observer language is different
// than the channel owner language.
if(strpos(strtolower($gender),strtolower(t('Female'))) !== false)
@ -1622,16 +1670,21 @@ function get_my_address() {
* If somebody arrives at our site using a zid, add their xchan to our DB if we
* don't have it already.
* And if they aren't already authenticated here, attempt reverse magic auth.
*
* @hooks zid_init
* * \e string \b zid - their zid
* * \e string \b url - the destination url
*/
function zid_init() {
$tmp_str = get_my_address();
if(validate_email($tmp_str)) {
$arr = array('zid' => $tmp_str, 'url' => App::$cmd);
call_hooks('zid_init',$arr);
$arr = [
'zid' => $tmp_str,
'url' => App::$cmd
];
/**
* @hooks zid_init
* * \e string \b zid - their zid
* * \e string \b url - the destination url
*/
call_hooks('zid_init', $arr);
if(! local_channel()) {
$r = q("select * from hubloc where hubloc_addr = '%s' order by hubloc_connected desc limit 1",
dbesc($tmp_str)
@ -1641,7 +1694,8 @@ function zid_init() {
}
if($r && remote_channel() && remote_channel() === $r[0]['hubloc_hash'])
return;
logger('zid_init: not authenticated. Invoking reverse magic-auth for ' . $tmp_str);
logger('Not authenticated. Invoking reverse magic-auth for ' . $tmp_str);
// try to avoid recursion - but send them home to do a proper magic auth
$query = App::$query_string;
$query = str_replace(array('?zid=','&zid='),array('?rzid=','&rzid='),$query);
@ -1650,7 +1704,7 @@ function zid_init() {
goaway($r[0]['hubloc_url'] . '/magic' . '?f=&rev=1&owa=1&dest=' . z_root() . $dest);
}
else
logger('zid_init: no hubloc found.');
logger('No hubloc found.');
}
}
}
@ -1673,21 +1727,23 @@ function zat_init() {
}
// Used from within PCSS themes to set theme parameters. If there's a
// puid request variable, that is the "page owner" and normally their theme
// settings take precedence; unless a local user sets the "always_my_theme"
// system pconfig, which means they don't want to see anybody else's theme
// settings except their own while on this site.
/**
* @brief Used from within PCSS themes to set theme parameters.
*
* If there's a puid request variable, that is the "page owner" and normally
* their theme settings take precedence; unless a local user sets the "always_my_theme"
* system pconfig, which means they don't want to see anybody else's theme
* settings except their own while on this site.
*
* @return int
*/
function get_theme_uid() {
$uid = (($_REQUEST['puid']) ? intval($_REQUEST['puid']) : 0);
if(local_channel()) {
if((get_pconfig(local_channel(),'system','always_my_theme')) || (! $uid))
return local_channel();
}
if(! $uid) {
if(! $uierd) {
$x = get_sys_channel();
if($x)
return $x['channel_id'];
@ -1700,9 +1756,9 @@ function get_theme_uid() {
* @brief Retrieves the path of the default_profile_photo for this system
* with the specified size.
*
* @param int $size
* one of (300, 80, 48)
* @returns string with path to profile photo
* @param int $size (optional) default 300
* one of (300, 80, 48)
* @return string with path to profile photo
*/
function get_default_profile_photo($size = 300) {
$scheme = get_config('system','default_profile_photo');
@ -1715,9 +1771,9 @@ function get_default_profile_photo($size = 300) {
/**
* @brief Test whether a given identity is NOT a member of the Hubzilla.
*
* @param string $s;
* @param string $s
* xchan_hash of the identity in question
* @returns boolean true or false
* @return boolean true or false
*/
function is_foreigner($s) {
return((strpbrk($s, '.:@')) ? true : false);
@ -1726,14 +1782,21 @@ function is_foreigner($s) {
/**
* @brief Test whether a given identity is a member of the Hubzilla.
*
* @param string $s;
* @param string $s
* xchan_hash of the identity in question
* @returns boolean true or false
* @return boolean true or false
*/
function is_member($s) {
return((is_foreigner($s)) ? false : true);
}
/**
* @brief Get chatpresence status for nick.
*
* @param string $nick
* @return array An associative array with
* * \e bool \b result
*/
function get_online_status($nick) {
$ret = array('result' => false);
@ -1748,6 +1811,7 @@ function get_online_status($nick) {
$hide = get_pconfig($r[0]['channel_id'],'system','hide_online_status');
if($hide)
return $ret;
$x = q("select cp_status from chatpresence where cp_xchan = '%s' and cp_room = 0 limit 1",
dbesc($r[0]['channel_hash'])
);
@ -1759,6 +1823,12 @@ function get_online_status($nick) {
}
/**
* @brief
*
* @param string $webbie
* @return array|boolean|string
*/
function remote_online_status($webbie) {
$result = false;
@ -1782,11 +1852,10 @@ function remote_online_status($webbie) {
/**
* @brief
* @brief Return the parsed identity selector HTML template.
*
* @return string
* @return string with parsed HTML channel_id_selet template
*/
function identity_selector() {
if(local_channel()) {
$r = q("select channel.*, xchan.* from channel left join xchan on channel.channel_hash = xchan.xchan_hash where channel.channel_account_id = %d and channel_removed = 0 order by channel_name ",
@ -1798,6 +1867,7 @@ function identity_selector() {
'$channels' => $r,
'$selected' => local_channel()
));
return $o;
}
}
@ -1809,14 +1879,17 @@ function identity_selector() {
function is_public_profile() {
if(! local_channel())
return false;
if(intval(get_config('system','block_public')))
return false;
$channel = App::get_channel();
if($channel) {
$perm = \Zotlabs\Access\PermissionLimits::Get($channel['channel_id'],'view_profile');
if($perm == PERMS_PUBLIC)
return true;
}
return false;
}
@ -1861,7 +1934,7 @@ function get_profile_fields_advanced($filter = 0) {
*
* @param int $channel_id
* The channel to disable notifications for
* @returns int
* @return int
* Current notification flag value. Send this to notifications_on() to restore the channel settings when finished
* with the activity requiring notifications_off();
*/
@ -1993,13 +2066,14 @@ function get_cover_photo($channel_id,$format = 'bbcode', $res = PHOTO_RES_COVER_
return $output;
}
/**
* @brief
* @brief Return parsed HTML zcard template.
*
* @param array $channel
* @param string $observer_hash
* @param array $args
* @return string
* @param string $observer_hash (optional)
* @param array $args (optional)
* @return string parsed HTML from \e zcard template
*/
function get_zcard($channel, $observer_hash = '', $args = array()) {
@ -2067,6 +2141,14 @@ function get_zcard($channel, $observer_hash = '', $args = array()) {
}
/**
* @brief Return parsed HTML embed zcard template.
*
* @param array $channel
* @param string $observer_hash (optional)
* @param array $args (optional)
* @return string parsed HTML from \e zcard_embed template
*/
function get_zcard_embed($channel, $observer_hash = '', $args = array()) {
logger('get_zcard_embed');
@ -2133,10 +2215,12 @@ function get_zcard_embed($channel, $observer_hash = '', $args = array()) {
}
/**
* @brief
* @brief Get a channel array from a channel nickname.
*
* @param string $nick
* @return mixed
* @param string $nick - A channel_address nickname
* @return array|boolean
* - array with channel entry
* - false if no channel with $nick was found
*/
function channelx_by_nick($nick) {
$r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_address = '%s' and channel_removed = 0 LIMIT 1",
@ -2147,10 +2231,10 @@ function channelx_by_nick($nick) {
}
/**
* @brief
* @brief Get a channel array by a channel_hash.
*
* @param string $hash
* @return mixed
* @return array|boolean false if channel ID not found, otherwise the channel array
*/
function channelx_by_hash($hash) {
$r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_hash = '%s' and channel_removed = 0 LIMIT 1",
@ -2161,13 +2245,13 @@ function channelx_by_hash($hash) {
}
/**
* @brief
* @brief Get a channel array by a channel ID.
*
* @param int $id
* @return mixed
* @param int $id A channel ID
* @return array|boolean false if channel ID not found, otherwise the channel array
*/
function channelx_by_n($id) {
$r = q("SELECT * FROM channel left join xchan on channel_hash = xchan_hash WHERE channel_id = %d and channel_removed = 0 LIMIT 1",
$r = q("SELECT * FROM channel LEFT JOIN xchan ON channel_hash = xchan_hash WHERE channel_id = %d AND channel_removed = 0 LIMIT 1",
dbesc($id)
);
@ -2177,7 +2261,7 @@ function channelx_by_n($id) {
/**
* @brief
*
* @param string $channel
* @param array $channel
* @return string
*/
function channel_reddress($channel) {
@ -2188,67 +2272,77 @@ function channel_reddress($channel) {
}
/**
* @brief Get manual channel conversation update config.
*
* Check the channel config \e manual_conversation_update, if not set fall back
* to global system config, defaults to 1 if nothing set.
*
* @param int $channel_id
* @return int
*/
function channel_manual_conv_update($channel_id) {
$x = get_pconfig($channel_id, 'system','manual_conversation_update');
$x = get_pconfig($channel_id, 'system', 'manual_conversation_update');
if($x === false)
$x = get_config('system','manual_conversation_update', 1);
$x = get_config('system', 'manual_conversation_update', 1);
return intval($x);
}
/**
* @brief Return parsed HTML remote_login template.
*
* @return string with parsed HTML from \e remote_login template
*/
function remote_login() {
$o = replace_macros(get_markup_template('remote_login.tpl'),array(
'$title' => t('Remote Authentication'),
'$desc' => t('Enter your channel address (e.g. channel@example.com)'),
'$submit' => t('Authenticate')
));
$o = replace_macros(get_markup_template('remote_login.tpl'),array(
'$title' => t('Remote Authentication'),
'$desc' => t('Enter your channel address (e.g. channel@example.com)'),
'$submit' => t('Authenticate')
));
return $o;
return $o;
}
function channel_store_lowlevel($arr) {
$store = [
'channel_account_id' => ((array_key_exists('channel_account_id',$arr)) ? $arr['channel_account_id'] : '0'),
'channel_primary' => ((array_key_exists('channel_primary',$arr)) ? $arr['channel_primary'] : '0'),
'channel_name' => ((array_key_exists('channel_name',$arr)) ? $arr['channel_name'] : ''),
'channel_address' => ((array_key_exists('channel_address',$arr)) ? $arr['channel_address'] : ''),
'channel_guid' => ((array_key_exists('channel_guid',$arr)) ? $arr['channel_guid'] : ''),
'channel_guid_sig' => ((array_key_exists('channel_guid_sig',$arr)) ? $arr['channel_guid_sig'] : ''),
'channel_hash' => ((array_key_exists('channel_hash',$arr)) ? $arr['channel_hash'] : ''),
'channel_timezone' => ((array_key_exists('channel_timezone',$arr)) ? $arr['channel_timezone'] : 'UTC'),
'channel_location' => ((array_key_exists('channel_location',$arr)) ? $arr['channel_location'] : ''),
'channel_theme' => ((array_key_exists('channel_theme',$arr)) ? $arr['channel_theme'] : ''),
'channel_startpage' => ((array_key_exists('channel_startpage',$arr)) ? $arr['channel_startpage'] : ''),
'channel_pubkey' => ((array_key_exists('channel_pubkey',$arr)) ? $arr['channel_pubkey'] : ''),
'channel_prvkey' => ((array_key_exists('channel_prvkey',$arr)) ? $arr['channel_prvkey'] : ''),
'channel_notifyflags' => ((array_key_exists('channel_notifyflags',$arr)) ? $arr['channel_notifyflags'] : '65535'),
'channel_pageflags' => ((array_key_exists('channel_pageflags',$arr)) ? $arr['channel_pageflags'] : '0'),
'channel_dirdate' => ((array_key_exists('channel_dirdate',$arr)) ? $arr['channel_dirdate'] : NULL_DATE),
'channel_lastpost' => ((array_key_exists('channel_lastpost',$arr)) ? $arr['channel_lastpost'] : NULL_DATE),
'channel_deleted' => ((array_key_exists('channel_deleted',$arr)) ? $arr['channel_deleted'] : NULL_DATE),
'channel_max_anon_mail' => ((array_key_exists('channel_max_anon_mail',$arr)) ? $arr['channel_max_anon_mail'] : '10'),
'channel_max_friend_req' => ((array_key_exists('channel_max_friend_req',$arr)) ? $arr['channel_max_friend_req'] : '10'),
'channel_expire_days' => ((array_key_exists('channel_expire_days',$arr)) ? $arr['channel_expire_days'] : '0'),
'channel_passwd_reset' => ((array_key_exists('channel_passwd_reset',$arr)) ? $arr['channel_passwd_reset'] : ''),
'channel_default_group' => ((array_key_exists('channel_default_group',$arr)) ? $arr['channel_default_group'] : ''),
'channel_allow_cid' => ((array_key_exists('channel_allow_cid',$arr)) ? $arr['channel_allow_cid'] : ''),
'channel_allow_gid' => ((array_key_exists('channel_allow_gid',$arr)) ? $arr['channel_allow_gid'] : ''),
'channel_deny_cid' => ((array_key_exists('channel_deny_cid',$arr)) ? $arr['channel_deny_cid'] : ''),
'channel_deny_gid' => ((array_key_exists('channel_deny_gid',$arr)) ? $arr['channel_deny_gid'] : ''),
'channel_removed' => ((array_key_exists('channel_removed',$arr)) ? $arr['channel_removed'] : '0'),
'channel_system' => ((array_key_exists('channel_system',$arr)) ? $arr['channel_system'] : '0'),
$store = [
'channel_account_id' => ((array_key_exists('channel_account_id',$arr)) ? $arr['channel_account_id'] : '0'),
'channel_primary' => ((array_key_exists('channel_primary',$arr)) ? $arr['channel_primary'] : '0'),
'channel_name' => ((array_key_exists('channel_name',$arr)) ? $arr['channel_name'] : ''),
'channel_address' => ((array_key_exists('channel_address',$arr)) ? $arr['channel_address'] : ''),
'channel_guid' => ((array_key_exists('channel_guid',$arr)) ? $arr['channel_guid'] : ''),
'channel_guid_sig' => ((array_key_exists('channel_guid_sig',$arr)) ? $arr['channel_guid_sig'] : ''),
'channel_hash' => ((array_key_exists('channel_hash',$arr)) ? $arr['channel_hash'] : ''),
'channel_timezone' => ((array_key_exists('channel_timezone',$arr)) ? $arr['channel_timezone'] : 'UTC'),
'channel_location' => ((array_key_exists('channel_location',$arr)) ? $arr['channel_location'] : ''),
'channel_theme' => ((array_key_exists('channel_theme',$arr)) ? $arr['channel_theme'] : ''),
'channel_startpage' => ((array_key_exists('channel_startpage',$arr)) ? $arr['channel_startpage'] : ''),
'channel_pubkey' => ((array_key_exists('channel_pubkey',$arr)) ? $arr['channel_pubkey'] : ''),
'channel_prvkey' => ((array_key_exists('channel_prvkey',$arr)) ? $arr['channel_prvkey'] : ''),
'channel_notifyflags' => ((array_key_exists('channel_notifyflags',$arr)) ? $arr['channel_notifyflags'] : '65535'),
'channel_pageflags' => ((array_key_exists('channel_pageflags',$arr)) ? $arr['channel_pageflags'] : '0'),
'channel_dirdate' => ((array_key_exists('channel_dirdate',$arr)) ? $arr['channel_dirdate'] : NULL_DATE),
'channel_lastpost' => ((array_key_exists('channel_lastpost',$arr)) ? $arr['channel_lastpost'] : NULL_DATE),
'channel_deleted' => ((array_key_exists('channel_deleted',$arr)) ? $arr['channel_deleted'] : NULL_DATE),
'channel_max_anon_mail' => ((array_key_exists('channel_max_anon_mail',$arr)) ? $arr['channel_max_anon_mail'] : '10'),
'channel_max_friend_req' => ((array_key_exists('channel_max_friend_req',$arr)) ? $arr['channel_max_friend_req'] : '10'),
'channel_expire_days' => ((array_key_exists('channel_expire_days',$arr)) ? $arr['channel_expire_days'] : '0'),
'channel_passwd_reset' => ((array_key_exists('channel_passwd_reset',$arr)) ? $arr['channel_passwd_reset'] : ''),
'channel_default_group' => ((array_key_exists('channel_default_group',$arr)) ? $arr['channel_default_group'] : ''),
'channel_allow_cid' => ((array_key_exists('channel_allow_cid',$arr)) ? $arr['channel_allow_cid'] : ''),
'channel_allow_gid' => ((array_key_exists('channel_allow_gid',$arr)) ? $arr['channel_allow_gid'] : ''),
'channel_deny_cid' => ((array_key_exists('channel_deny_cid',$arr)) ? $arr['channel_deny_cid'] : ''),
'channel_deny_gid' => ((array_key_exists('channel_deny_gid',$arr)) ? $arr['channel_deny_gid'] : ''),
'channel_removed' => ((array_key_exists('channel_removed',$arr)) ? $arr['channel_removed'] : '0'),
'channel_system' => ((array_key_exists('channel_system',$arr)) ? $arr['channel_system'] : '0'),
'channel_moved' => ((array_key_exists('channel_moved',$arr)) ? $arr['channel_moved'] : ''),
'channel_password' => ((array_key_exists('channel_password',$arr)) ? $arr['channel_password'] : ''),
'channel_salt' => ((array_key_exists('channel_salt',$arr)) ? $arr['channel_salt'] : '')
];
return create_table_from_array('channel',$store);
return create_table_from_array('channel', $store);
}
function profile_store_lowlevel($arr) {
@ -2304,16 +2398,22 @@ function profile_store_lowlevel($arr) {
}
// Included here for completeness, but this is a very dangerous operation.
// It is the caller's responsibility to confirm the requestor's intent and
// authorisation to do this.
function account_remove($account_id,$local = true,$unset_session = true) {
/**
* Included here for completeness, but this is a very dangerous operation.
* It is the caller's responsibility to confirm the requestor's intent and
* authorisation to do this.
*
* @param int $account_id
* @param boolean $local (optional) default true
* @param boolean $unset_session (optional) default true
* @return boolean|array
*/
function account_remove($account_id, $local = true, $unset_session = true) {
logger('account_remove: ' . $account_id);
if(! intval($account_id)) {
logger('account_remove: no account.');
logger('No account.');
return false;
}
@ -2334,7 +2434,7 @@ function account_remove($account_id,$local = true,$unset_session = true) {
$account_email=$r[0]['account_email'];
if(! $r) {
logger('account_remove: No account with id: ' . $account_id);
logger('No account with id: ' . $account_id);
return false;
}
@ -2351,7 +2451,6 @@ function account_remove($account_id,$local = true,$unset_session = true) {
intval($account_id)
);
if ($unset_session) {
App::$session->nuke();
notice( sprintf(t('Account \'%s\' deleted'),$account_email) . EOL);
@ -2364,8 +2463,6 @@ function account_remove($account_id,$local = true,$unset_session = true) {
/**
* @brief Removes a channel.
*
* @hooks channel_remove
* * \e array \b entry from channel tabel for $channel_id
* @param int $channel_id
* @param boolean $local default true
* @param boolean $unset_session default false
@ -2386,6 +2483,11 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
$channel = $r[0];
/**
* @hooks channel_remove
* Called when removing a channel.
* * \e array with entry from channel tabel for $channel_id
*/
call_hooks('channel_remove', $r[0]);
if(! $local) {
@ -2457,6 +2559,7 @@ function channel_remove($channel_id, $local = true, $unset_session = false) {
$rr = q("update account set account_default_channel = %d where account_id = %d",
intval($r[0]['channel_id']),
intval(App::$account['account_id']));
logger("Default channel deleted, changing default to channel_id " . $r[0]['channel_id']);
}
else {
@ -2531,20 +2634,30 @@ function channel_codeallowed($channel_id) {
return true;
return false;
}
function anon_identity_init($reqvars) {
$x = [ 'request_vars' => $reqvars, 'xchan' => null, 'success' => 'unset' ];
call_hooks('anon_identity_init',$x);
$x = [
'request_vars' => $reqvars,
'xchan' => null,
'success' => 'unset'
];
/**
* @hooks anon_identity_init
* * \e array \b request_vars
* * \e string \b xchan - return value
* * \e string|int \b success - Must be a number, so xchan return value gets used
*/
call_hooks('anon_identity_init', $x);
if($x['success'] !== 'unset' && intval($x['success']) && $x['xchan'])
return $x['xchan'];
// allow a captcha handler to over-ride
// allow a captcha handler to over-ride
if($x['success'] !== 'unset' && (intval($x['success']) === 0))
return false;
return false;
$anon_name = strip_tags(trim($reqvars['anonname']));
$anon_email = strip_tags(trim($reqvars['anonmail']));
@ -2571,7 +2684,7 @@ function anon_identity_init($reqvars) {
);
if(! $x) {
xchan_store_lowlevel([
xchan_store_lowlevel([
'xchan_guid' => $anon_email,
'xchan_hash' => $hash,
'xchan_name' => $anon_name,
@ -2579,7 +2692,7 @@ function anon_identity_init($reqvars) {
'xchan_network' => 'unknown',
'xchan_name_date' => datetime_convert()
]);
$x = q("select * from xchan where xchan_guid = '%s' and xchan_hash = '%s' and xchan_network = 'unknown' limit 1",
dbesc($anon_email),
@ -2597,13 +2710,18 @@ function anon_identity_init($reqvars) {
dbesc($anon_email),
dbesc($hash)
);
}
return $x[0];
}
/**
* @brief Create a channel array from proxy channel (pchan).
*
* @param array $pchan The proxy channel
* @return array channel array
*/
function pchan_to_chan($pchan) {
$chan = $pchan;
$chan['channel_address'] = $pchan['pchan_guid'];
@ -2611,5 +2729,7 @@ function pchan_to_chan($pchan) {
$chan['channel_pubkey'] = $pchan['pchan_pubkey'];
$chan['channel_prvkey'] = $pchan['pchan_prvkey'];
$chan['channel_name'] = $pchan['xchan_name'];
return $chan;
}
}

View file

@ -8,6 +8,8 @@
/**
* @brief Two-level sort for timezones.
*
* Can be used in usort() to sort timezones.
*
* @param string $a
* @param string $b
* @return number
@ -27,13 +29,14 @@ function timezone_cmp($a, $b) {
function is_null_date($s) {
if($s === '0000-00-00 00:00:00' || $s === '0001-01-01 00:00:00')
return true;
return false;
}
/**
* @brief Return timezones grouped (primarily) by continent.
*
* @see timezone_cmp()
* @return array
*/
function get_timezones( ){
@ -54,7 +57,7 @@ function get_timezones( ){
$city = $ex[0];
$continent = t('Miscellaneous');
}
$city = str_replace('_', ' ', t($city));
$city = str_replace('_', ' ', t($city));
if (!x($continents, $ex[0])) $continents[$ex[0]] = array();
$continents[$continent][$value] = $city;
@ -109,7 +112,7 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
try {
$d = new DateTime($s, $from_obj);
} catch(Exception $e) {
logger('datetime_convert: exception: ' . $e->getMessage());
logger('exception: ' . $e->getMessage());
$d = new DateTime('now', $from_obj);
}
@ -128,7 +131,7 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
* @brief Wrapper for date selector, tailored for use in birthday fields.
*
* @param string $dob Date of Birth
* @return string
* @return string Parsed HTML with selector
*/
function dob($dob) {
@ -161,59 +164,62 @@ function dob($dob) {
}
/**
* returns a date selector
* @param $format
* format string, e.g. 'ymd' or 'mdy'. Not currently supported
* @param $min
* unix timestamp of minimum date
* @param $max
* unix timestap of maximum date
* @param $default
* unix timestamp of default date
* @param $id
* id and name of datetimepicker (defaults to "datetimepicker")
* @brief Returns a date selector.
*
* @see datetimesel()
* @param string $format
* format string, e.g. 'ymd' or 'mdy'. Not currently supported
* @param DateTime $min
* unix timestamp of minimum date
* @param DateTime $max
* unix timestap of maximum date
* @param DateTime $default
* unix timestamp of default date
* @param string $id
* id and name of datetimepicker (defaults to "datetimepicker")
*/
function datesel($format, $min, $max, $default, $id = 'datepicker') {
return datetimesel($format, $min, $max, $default, '', $id,true, false, '', '');
return datetimesel($format, $min, $max, $default, '', $id, true, false, '', '');
}
/**
* returns a time selector
* @param $format
* format string, e.g. 'ymd' or 'mdy'. Not currently supported
* @param $h
* already selected hour
* @param $m
* @brief Returns a time selector.
*
* @param string $format
* format string, e.g. 'ymd' or 'mdy'. Not currently supported
* @param string $h
* already selected hour
* @param string $m
* already selected minute
* @param $id
* @param string $id
* id and name of datetimepicker (defaults to "timepicker")
*/
function timesel($format, $h, $m, $id='timepicker') {
return datetimesel($format,new DateTime(),new DateTime(),new DateTime("$h:$m"),'', $id,false,true);
return datetimesel($format, new DateTime(), new DateTime(), new DateTime("$h:$m"), '', $id, false, true);
}
/**
* @brief Returns a datetime selector.
*
* @param string $format
* format string, e.g. 'ymd' or 'mdy'. Not currently supported
* @param $min
* unix timestamp of minimum date
* @param $max
* unix timestap of maximum date
* @param $default
* unix timestamp of default date
* format string, e.g. 'ymd' or 'mdy'. Not currently supported
* @param DateTime $min
* unix timestamp of minimum date
* @param DateTime $max
* unix timestap of maximum date
* @param DateTime $default
* unix timestamp of default date
* @param string $label
* @param string $id
* id and name of datetimepicker (defaults to "datetimepicker")
* id and name of datetimepicker (defaults to "datetimepicker")
* @param boolean $pickdate
* true to show date picker (default)
* true to show date picker (default)
* @param boolean $picktime
* true to show time picker (default)
* @param $minfrom
* set minimum date from picker with id $minfrom (none by default)
* @param $maxfrom
* set maximum date from picker with id $maxfrom (none by default)
* true to show time picker (default)
* @param DateTime $minfrom
* set minimum date from picker with id $minfrom (none by default)
* @param DateTime $maxfrom
* set maximum date from picker with id $maxfrom (none by default)
* @param boolean $required default false
* @param int $first_day (optional) default 0
* @return string Parsed HTML output.
@ -343,9 +349,6 @@ function plural_dates($k,$n) {
}
}
/**
* @brief Returns timezone correct age in years.
*
@ -418,7 +421,7 @@ function get_dim($y, $m) {
*
* @param int $y Year
* @param int $m Month (1=January, 12=December)
* @return day 0 = Sunday through 6 = Saturday
* @return string day 0 = Sunday through 6 = Saturday
*/
function get_first_dim($y, $m) {
$d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m));

View file

@ -1,15 +1,16 @@
<?php
/**
* @file include/event.php
* @brief Event related functions.
*/
use Sabre\VObject;
/**
* @file include/event.php
*/
/**
* @brief Returns an event as HTML
* @brief Returns an event as HTML.
*
* @param array $ev
* @return string
* @return string HTML formatted event
*/
function format_event_html($ev) {
@ -21,7 +22,7 @@ function format_event_html($ev) {
$bd_format = t('l F d, Y \@ g:i A') ; // Friday January 18, 2011 @ 8:01 AM
//todo: move this to template
/// @TODO move this to template
$o = '<div class="vevent">' . "\r\n";
@ -29,27 +30,27 @@ function format_event_html($ev) {
$o .= '<div class="event-start"><span class="event-label">' . t('Starts:') . '</span>&nbsp;<span class="dtstart" title="'
. datetime_convert('UTC', 'UTC', $ev['dtstart'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['dtstart'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
: day_translate(datetime_convert('UTC', 'UTC',
$ev['dtstart'] , $bd_format)))
. '</span></div>' . "\r\n";
if(! $ev['nofinish'])
$o .= '<div class="event-end" ><span class="event-label">' . t('Finishes:') . '</span>&nbsp;<span class="dtend" title="'
. datetime_convert('UTC','UTC',$ev['dtend'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' ))
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
. '" >'
. (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(),
$ev['dtend'] , $bd_format ))
: day_translate(datetime_convert('UTC', 'UTC',
: day_translate(datetime_convert('UTC', 'UTC',
$ev['dtend'] , $bd_format )))
. '</span></div>' . "\r\n";
$o .= '<div class="event-description">' . zidify_links(smilies(bbcode($ev['description']))) . '</div>' . "\r\n";
if(strlen($ev['location']))
$o .= '<div class="event-location"><span class="event-label"> ' . t('Location:') . '</span>&nbsp;<span class="location">'
$o .= '<div class="event-location"><span class="event-label"> ' . t('Location:') . '</span>&nbsp;<span class="location">'
. zidify_links(smilies(bbcode($ev['location'])))
. '</span></div>' . "\r\n";
@ -123,9 +124,9 @@ function format_event_ical($ev) {
$o .= "\r\nCREATED:" . datetime_convert('UTC','UTC', $ev['created'],'Ymd\\THis\\Z');
$o .= "\r\nLAST-MODIFIED:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
$o .= "\r\nDTSTAMP:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
if($ev['dtstart'])
if($ev['dtstart'])
$o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['dtstart'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
if($ev['dtend'] && ! $ev['nofinish'])
if($ev['dtend'] && ! $ev['nofinish'])
$o .= "\r\nDTEND:" . datetime_convert('UTC','UTC', $ev['dtend'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
if($ev['summary']) {
$o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']);
@ -143,7 +144,7 @@ function format_event_ical($ev) {
$o .= "\r\nPRIORITY:" . intval($ev['event_priority']);
$o .= "\r\nUID:" . $ev['event_hash'] ;
$o .= "\r\nEND:VEVENT\r\n";
return $o;
}
@ -156,9 +157,9 @@ function format_todo_ical($ev) {
$o .= "\r\nCREATED:" . datetime_convert('UTC','UTC', $ev['created'],'Ymd\\THis\\Z');
$o .= "\r\nLAST-MODIFIED:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
$o .= "\r\nDTSTAMP:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
if($ev['dtstart'])
if($ev['dtstart'])
$o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['dtstart'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
if($ev['dtend'] && ! $ev['nofinish'])
if($ev['dtend'] && ! $ev['nofinish'])
$o .= "\r\nDUE:" . datetime_convert('UTC','UTC', $ev['dtend'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
if($ev['summary']) {
$o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']);
@ -170,8 +171,8 @@ function format_todo_ical($ev) {
$o .= "\r\nCOMPLETED:" . datetime_convert('UTC','UTC', $ev['event_status_date'],'Ymd\\THis\\Z');
}
if(intval($ev['event_percent']))
$o .= "\r\nPERCENT-COMPLETE:" . $ev['event_percent'];
if(intval($ev['event_sequence']))
$o .= "\r\nPERCENT-COMPLETE:" . $ev['event_percent'];
if(intval($ev['event_sequence']))
$o .= "\r\nSEQUENCE:" . $ev['event_sequence'];
if($ev['location']) {
$o .= "\r\nLOCATION:" . format_ical_text($ev['location']);
@ -196,12 +197,13 @@ function format_ical_text($s) {
$s = html2plain(bbcode($s));
$s = str_replace(["\r\n","\n"],["",""],$s);
return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true));
return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true));
}
function format_ical_sourcetext($s) {
$s = base64_encode($s);
return(wordwrap(str_replace(['\\',',',';'],['\\\\','\\,','\\;'],$s),72,"\r\n ",true));
}
@ -225,7 +227,7 @@ function format_event_bbcode($ev) {
if(($ev['dtend']) && (! $ev['nofinish']))
$o .= '[event-finish]' . $ev['dtend'] . '[/event-finish]';
if($ev['location'])
$o .= '[event-location]' . $ev['location'] . '[/event-location]';
@ -253,7 +255,6 @@ function bbtoevent($s) {
$ev = array();
$match = '';
if(preg_match("/\[event\](.*?)\[\/event\]/is",$s,$match)) {
// only parse one object per event tag
@ -306,7 +307,7 @@ function bbtoevent($s) {
*
* @see ev_compare()
* @param array $arr
* @return sorted array
* @return array Date sorted array of events
*/
function sort_by_date($arr) {
if (is_array($arr))
@ -318,6 +319,8 @@ function sort_by_date($arr) {
/**
* @brief Compare function for events.
*
* This function can be used in usort() to sort events by date.
*
* @see sort_by_date()
* @param array $a
* @param array $b
@ -375,8 +378,19 @@ function event_store_event($arr) {
}
}
$hook_info = [ 'event' => $arr, 'existing_event' => $existing_event, 'cancel' => false ];
call_hooks('event_store_event',$hook_info);
$hook_info = [
'event' => $arr,
'existing_event' => $existing_event,
'cancel' => false
];
/**
* @hooks event_store_event
* Called when an event record is created or updated.
* * \e array \b event
* * \e array \b existing_event
* * \e boolean \b cancel - default false
*/
call_hooks('event_store_event', $hook_info);
if($hook_info['cancel'])
return false;
@ -386,7 +400,7 @@ function event_store_event($arr) {
if($existing_event) {
if($existing_event['edited'] >= $arr['edited']) {
// Nothing has changed.
// Nothing has changed.
return $existing_event;
}
@ -444,7 +458,6 @@ function event_store_event($arr) {
// New event. Store it.
if(array_key_exists('external_id',$arr))
$hash = $arr['external_id'];
elseif(array_key_exists('event_hash',$arr))
@ -531,7 +544,7 @@ function event_addtocal($item_id, $uid) {
}
if($ev->private)
$ev['allow_cid'] = '<' . $channel['channel_hash'] . '>';
$ev['allow_cid'] = '<' . $channel['channel_hash'] . '>';
else {
$acl = new Zotlabs\Access\AccessList($channel);
$x = $acl->get();
@ -596,14 +609,12 @@ function ical_to_ev($s) {
date_default_timezone_set($saved_timezone);
return $ev;
}
function parse_vobject($ical, $type) {
$ev = [];
if(! isset($ical->DTSTART)) {
@ -698,10 +709,8 @@ function parse_vobject($ical, $type) {
function parse_ical_file($f,$uid) {
require_once('vendor/autoload.php');
require_once('vendor/autoload.php');
$s = @file_get_contents($f);
@ -731,6 +740,7 @@ require_once('vendor/autoload.php');
if($ical)
return true;
return false;
}
@ -779,7 +789,6 @@ function event_import_ical($ical, $uid) {
$ev['created'] = datetime_convert('UTC','UTC',$created->format(\DateTime::W3C));
}
if(isset($ical->{'LAST-MODIFIED'})) {
$edited = $ical->{'LAST-MODIFIED'}->getDateTime();
$ev['edited'] = datetime_convert('UTC','UTC',$edited->format(\DateTime::W3C));
@ -814,7 +823,7 @@ function event_import_ical($ical, $uid) {
else
$ev['external_id'] = $evuid;
}
if($ev['summary'] && $ev['dtstart']) {
$ev['event_xchan'] = $channel['channel_hash'];
$ev['uid'] = $channel['channel_id'];
@ -822,7 +831,7 @@ function event_import_ical($ical, $uid) {
$ev['private'] = 1;
$ev['allow_cid'] = '<' . $channel['channel_hash'] . '>';
logger('storing event: ' . print_r($ev,true), LOGGER_ALL);
logger('storing event: ' . print_r($ev,true), LOGGER_ALL);
$event = event_store_event($ev);
if($event) {
$item_id = event_store_item($ev,$event);
@ -831,7 +840,6 @@ function event_import_ical($ical, $uid) {
}
return false;
}
function event_ical_get_sourcetext($s) {
@ -931,7 +939,7 @@ function event_import_ical_task($ical, $uid) {
if(isset($ical->SEQUENCE)) {
$ev['event_sequence'] = (string) $ical->SEQUENCE;
// see if our stored event is more current than the one we're importing
if((intval($ev['event_sequence']) <= intval($stored_event['event_sequence']))
if((intval($ev['event_sequence']) <= intval($stored_event['event_sequence']))
&& ($ev['edited'] <= $stored_event['edited']))
return false;
}
@ -958,7 +966,7 @@ function event_import_ical_task($ical, $uid) {
$ev['private'] = 1;
$ev['allow_cid'] = '<' . $channel['channel_hash'] . '>';
logger('storing event: ' . print_r($ev,true), LOGGER_ALL);
logger('storing event: ' . print_r($ev,true), LOGGER_ALL);
$event = event_store_event($ev);
if($event) {
$item_id = event_store_item($ev,$event);
@ -967,14 +975,10 @@ function event_import_ical_task($ical, $uid) {
}
return false;
}
function event_store_item($arr, $event) {
require_once('include/datetime.php');
@ -995,7 +999,6 @@ function event_store_item($arr, $event) {
}
$item_arr = array();
$prefix = '';
// $birthday = false;
@ -1008,9 +1011,9 @@ function event_store_item($arr, $event) {
$prefix = t('This event has been added to your calendar.');
// $birthday = true;
// The event is created on your own site by the system, but appears to belong
// The event is created on your own site by the system, but appears to belong
// to the birthday person. It also isn't propagated - so we need to prevent
// folks from trying to comment on it. If you're looking at this and trying to
// folks from trying to comment on it. If you're looking at this and trying to
// fix it, you'll need to completely change the way birthday events are created
// and send them out from the source. This has its own issues.
@ -1048,9 +1051,10 @@ function event_store_item($arr, $event) {
$private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0);
// @FIXME can only update sig if we have the author's channel on this site
// Until fixed, set it to nothing so it won't give us signature errors
/**
* @FIXME can only update sig if we have the author's channel on this site
* Until fixed, set it to nothing so it won't give us signature errors.
*/
$sig = '';
q("UPDATE item SET title = '%s', body = '%s', obj = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', sig = '%s', item_flags = %d, item_private = %d, obj_type = '%s' WHERE id = %d AND uid = %d",
@ -1090,6 +1094,10 @@ function event_store_item($arr, $event) {
}
$item_id = $r[0]['id'];
/**
* @hooks event_updated
* Called when an event record is modified.
*/
call_hooks('event_updated', $event['id']);
return $item_id;
@ -1103,7 +1111,7 @@ function event_store_item($arr, $event) {
$item_wall = 0;
$item_origin = 0;
$item_thread_top = 0;
$item_thread_top = 0;
if($item) {
$item_arr['id'] = $item['id'];
@ -1196,6 +1204,10 @@ function event_store_item($arr, $event) {
$item_id = $res['item_id'];
/**
* @hooks event_created
* Called when an event record is created.
*/
call_hooks('event_created', $event['id']);
return $item_id;
@ -1216,25 +1228,24 @@ function todo_stat() {
function tasks_fetch($arr) {
if(! local_channel())
return;
if(! local_channel())
return;
$ret = array();
$sql_extra = " and event_status != 'COMPLETED' ";
if($arr && $arr['all'] == 1)
$sql_extra = '';
$ret = array();
$sql_extra = " and event_status != 'COMPLETED' ";
if($arr && $arr['all'] == 1)
$sql_extra = '';
$r = q("select * from event where etype = 'task' and uid = %d $sql_extra order by created desc",
intval(local_channel())
);
$r = q("select * from event where etype = 'task' and uid = %d $sql_extra order by created desc",
intval(local_channel())
);
$ret['success'] = (($r) ? true : false);
if($r) {
$ret['tasks'] = $r;
}
$ret['success'] = (($r) ? true : false);
if($r) {
$ret['tasks'] = $r;
}
return $ret;
}
function cdav_principal($uri) {

View file

@ -1,5 +1,8 @@
<?php
/**
* @file include/feedutils.php
* @brief Some functions to work with XML feeds.
*/
/**
* @brief Return an Atom feed for channel.
@ -57,7 +60,6 @@ function get_public_feed($channel, $params) {
* @param array $params
* @return string with an atom feed
*/
function get_feed_for($channel, $observer_hash, $params) {
if(! $channel)
@ -105,12 +107,28 @@ function get_feed_for($channel, $observer_hash, $params) {
));
$x = [ 'xml' => $atom, 'channel' => $channel, 'observer_hash' => $observer_hash, 'params' => $params ];
call_hooks('atom_feed_top',$x);
$x = [
'xml' => $atom,
'channel' => $channel,
'observer_hash' => $observer_hash,
'params' => $params
];
/**
* @hooks atom_feed_top
* * \e string \b xml - the generated feed and what will get returned from the hook
* * \e array \b channel
* * \e string \b observer_hash
* * \e array \b params
*/
call_hooks('atom_feed_top', $x);
$atom = $x['xml'];
// a much simpler interface
/**
* @hooks atom_feed
* A much simpler interface than atom_feed_top.
* * \e string - the feed after atom_feed_top hook
*/
call_hooks('atom_feed', $atom);
$items = items_fetch(
@ -135,11 +153,14 @@ function get_feed_for($channel, $observer_hash, $params) {
if($item['item_private'])
continue;
/** @BUG $owner is undefined in this call */
$atom .= atom_entry($item, $type, null, $owner, true, '', $params['compat']);
}
}
/**
* @hooks atom_feed_end
* \e string - The created XML feed as a string without closing tag
*/
call_hooks('atom_feed_end', $atom);
$atom .= '</feed>' . "\r\n";
@ -344,6 +365,7 @@ function get_atom_elements($feed, $item, &$author) {
}
}
// check for a yahoo media element (github etc.)
if(! $author['author_photo']) {
@ -356,7 +378,6 @@ function get_atom_elements($feed, $item, &$author) {
// No photo/profile-link on the item - look at the feed level
if((! (x($author,'author_link'))) || (! (x($author,'author_photo')))) {
$rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
@ -396,7 +417,7 @@ function get_atom_elements($feed, $item, &$author) {
// new style
$ostatus_conversation = normalise_id(unxmlify($rawcnv[0]['attribs']['']['ref']));
if(! $ostatus_conversation) {
// old style
// old style
$ostatus_conversation = normalise_id(unxmlify($rawcnv[0]['data']));
}
if($ostatus_conversation) {
@ -406,7 +427,7 @@ function get_atom_elements($feed, $item, &$author) {
}
$ostatus_protocol = (($ostatus_conversation) ? true : false);
$mastodon = (($item->get_item_tags('http://mastodon.social/schema/1.0','scope')) ? true : false);
if($mastodon) {
$ostatus_protocol = true;
@ -645,7 +666,7 @@ function get_atom_elements($feed, $item, &$author) {
$res['attach'][] = array('href' => $link, 'length' => $len, 'type' => $type, 'title' => $title );
}
}
$rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
@ -723,7 +744,6 @@ function get_atom_elements($feed, $item, &$author) {
$res['target'] = $obj;
}
if(array_key_exists('verb',$res) && $res['verb'] === ACTIVITY_SHARE
&& array_key_exists('obj_type',$res) && in_array($res['obj_type'], [ ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT, ACTIVITY_OBJ_ACTIVITY ] )) {
@ -737,7 +757,13 @@ function get_atom_elements($feed, $item, &$author) {
'author' => $author,
'result' => $res
];
/**
* @hooks parse_atom
* * \e SimplePie \b feed - The original SimplePie feed
* * \e array \b item
* * \e array \b author
* * \e array \b result - the result array that will also get returned
*/
call_hooks('parse_atom', $arr);
logger('author: ' .print_r($arr['author'], true), LOGGER_DATA);
@ -782,7 +808,7 @@ function feed_get_reshare(&$res,$item) {
$share['avatar'] = z_root() . '/' . get_default_profile_photo(80);
if(! $share['profile'])
$share['profile'] = z_root();
$child = $rawobj[0]['child'];
@ -809,7 +835,7 @@ function feed_get_reshare(&$res,$item) {
$body = html2bbcode($body);
}
}
$attach = $share['links'];
if($attach) {
@ -845,16 +871,16 @@ function feed_get_reshare(&$res,$item) {
}
}
}
if((! $body) && ($share['alternate'])) {
$body = $share['alternate'];
}
}
$res['body'] = "[share author='" . urlencode($share['author']) .
$res['body'] = "[share author='" . urlencode($share['author']) .
"' profile='" . $share['profile'] .
"' avatar='" . $share['avatar'] .
"' link='" . $share['alternate'] .
"' posted='" . $share['created'] .
"' posted='" . $share['created'] .
"' message_id='" . $share['message_id'] . "']";
$res['body'] .= $body;
@ -864,7 +890,6 @@ function feed_get_reshare(&$res,$item) {
}
/**
* @brief Encodes SimplePie_Item link arrays.
*
@ -940,7 +965,7 @@ function process_feed_tombstones($feed,$importer,$contact,$pass) {
*
* @param string $xml
* The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
* @param $importer
* @param array $importer
* The contact_record (joined to user_record) of the local user who owns this
* relationship. It is this person's stuff that is going to be updated.
* @param[in,out] array $contact
@ -1103,7 +1128,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
// Update content if 'updated' changes
if($r) {
if(activity_match($datarray['verb'],ACTIVITY_DELETE)
if(activity_match($datarray['verb'],ACTIVITY_DELETE)
&& $datarray['author_xchan'] === $r[0]['author_xchan']) {
if(! intval($r[0]['item_deleted'])) {
logger('deleting item ' . $r[0]['id'] . ' mid=' . $datarray['mid'], LOGGER_DEBUG);
@ -1147,6 +1172,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$datarray['parent_mid'] = $pmid;
}
}
if(($item_parent_mid) && (! $pmid)) {
logger('find_parent: matched in-reply-to: ' . $parent_mid, LOGGER_DEBUG);
$pmid = $item_parent_mid[0]['parent_mid'];
@ -1172,7 +1198,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
dbesc($parent_mid),
intval($importer['channel_id'])
);
if($x) {
$item_parent_mid = $x;
$pmid = $x[0]['parent_mid'];
@ -1205,7 +1231,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
);
if($r) {
$parent_item = $r[0];
if(intval($parent_item['item_nocomment']) || $parent_item['comment_policy'] === 'none'
if(intval($parent_item['item_nocomment']) || $parent_item['comment_policy'] === 'none'
|| ($parent_item['comments_closed'] > NULL_DATE && $parent_item['comments_closed'] < datetime_convert())) {
logger('comments disabled for post ' . $parent_item['mid']);
continue;
@ -1215,7 +1241,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
$allowed = false;
if($parent_item) {
if($parent_item['owner_xchan'] == $importer['channel_hash'])
if($parent_item['owner_xchan'] == $importer['channel_hash'])
$allowed = perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'post_comments');
else
$allowed = true;
@ -1230,16 +1256,17 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
// interactive feeds (such as OStatus) downstream to our followers
// We do not want to set it for non-interactive feeds or conversations we do not own
if(array_key_exists('send_downstream',$importer) && intval($importer['send_downstream'])
if(array_key_exists('send_downstream',$importer) && intval($importer['send_downstream'])
&& ($parent_item['owner_xchan'] == $importer['channel_hash'])) {
$send_downstream = true;
}
}
else {
if((! perm_is_allowed($importer['channel_id'],$contact['xchan_hash'],'send_stream')) && (! $importer['system'])) {
// @fixme check for and process ostatus autofriend
// otherwise
/**
* @fixme check for and process ostatus autofriend
* otherwise ignore this author.
*/
logger('Ignoring this author.');
continue;
}
@ -1249,13 +1276,13 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
// immediate parent wasn't found. Turn into a top-level post if permissions allow
// but save the thread_parent in case we need to refer to it later.
if(! post_is_importable($datarray, $contact))
continue;
$datarray['parent_mid'] = $datarray['mid'];
set_iconfig($datarray,'system','parent_mid',$parent_mid,true);
}
// allow likes of comments
@ -1306,7 +1333,6 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
}
// if we have everything but a photo, provide the default profile photo
if($author['author_name'] && $author['author_link'] && (! $author['author_photo']))
@ -1364,7 +1390,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) {
// Update content if 'updated' changes
if($r) {
if(activity_match($datarray['verb'],ACTIVITY_DELETE)
if(activity_match($datarray['verb'],ACTIVITY_DELETE)
&& $datarray['author_xchan'] === $r[0]['author_xchan']) {
if(! intval($r[0]['item_deleted'])) {
logger('deleting item ' . $r[0]['id'] . ' mid=' . $datarray['mid'], LOGGER_DEBUG);
@ -1426,12 +1452,12 @@ function feed_conversation_fetch($importer,$contact,$parent_link) {
// GNU-Social flavoured feeds
if(strpos($parent_link,'/notice/')) {
$link = str_replace('/notice/','/api/statuses/show/',$parent_link) . '.atom';
}
}
// Mastodon flavoured feeds
if(strpos($parent_link,'/users/') && strpos($parent_link,'/updates/')) {
$link = $parent_link . '.atom';
}
}
if(! $link)
return false;
@ -1446,21 +1472,21 @@ function feed_conversation_fetch($importer,$contact,$parent_link) {
$data = $fetch['body'];
// We will probably receive an atom 'entry' and not an atom 'feed'. Unfortunately
// our parser is a bit strict about compliance so we'll insert just enough of a feed
// tag to trick it into believing it's a compliant feed.
// our parser is a bit strict about compliance so we'll insert just enough of a feed
// tag to trick it into believing it's a compliant feed.
if(! strstr($data,'<feed')) {
$data = str_replace('<entry ','<feed xmlns="http://www.w3.org/2005/Atom"><entry ',$data);
$data = str_replace('<entry ','<feed xmlns="http://www.w3.org/2005/Atom"><entry ',$data);
$data .= '</feed>';
}
}
consume_feed($data,$importer,$contact,1);
consume_feed($data,$importer,$contact,2);
return true;
}
/**
* @brief Normalise an id.
*
@ -1479,7 +1505,7 @@ function normalise_id($id) {
*
* @param string $xml
* The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
* @param $importer
* @param array $importer (unused)
* The contact_record (joined to user_record) of the local user who owns this
* relationship. It is this person's stuff that is going to be updated.
*/
@ -1617,6 +1643,7 @@ function feed_meta($xml) {
return $ret;
}
/**
* @brief Not yet implemented function to update feed item.
*
@ -1627,6 +1654,7 @@ function update_feed_item($uid, $datarray) {
item_store_update($datarray);
}
/**
* @brief Fetch the content of a feed and further consume it.
*
@ -1659,11 +1687,10 @@ function handle_feed($uid, $abook_id, $url) {
}
}
/**
* @brief Return a XML tag with author information.
*
* @hooks \b atom_author Possibility to add further tags to returned XML string
* * \e string The created XML tag as a string without closing tag
* @param string $tag The XML tag to create
* @param string $nick preferred username
* @param string $name displayed name of the author
@ -1695,6 +1722,11 @@ function atom_author($tag, $nick, $name, $uri, $h, $w, $type, $photo) {
$o .= ' <poco:preferredUsername>' . $nick . '</poco:preferredUsername>' . "\r\n";
$o .= ' <poco:displayName>' . $name . '</poco:displayName>' . "\r\n";
/**
* @hooks atom_author
* Possibility to add further tags to returned XML string
* * \e string - The created XML tag as a string without closing tag
*/
call_hooks('atom_author', $o);
$o .= "</$tag>\r\n";
@ -1703,9 +1735,15 @@ function atom_author($tag, $nick, $name, $uri, $h, $w, $type, $photo) {
}
function atom_render_author($tag,$xchan) {
/**
* @brief
*
* @param string $tag
* @param array $xchan
* @return string An xml tag
*/
function atom_render_author($tag, $xchan) {
$nick = xmlify(substr($xchan['xchan_addr'],0,strpos($xchan['xchan_addr'],'@')));
$id = xmlify($xchan['xchan_url']);
$name = xmlify($xchan['xchan_name']);
@ -1724,13 +1762,15 @@ function atom_render_author($tag,$xchan) {
$o .= ' <poco:preferredUsername>' . $nick . '</poco:preferredUsername>' . "\r\n";
$o .= ' <poco:displayName>' . $name . '</poco:displayName>' . "\r\n";
/**
* @hooks atom_render_author
* * \e string - The created XML tag as a string without closing tag
*/
call_hooks('atom_render_author', $o);
$o .= "</$tag>\r\n";
return $o;
}
function compat_photos_list($s) {
@ -1740,7 +1780,7 @@ function compat_photos_list($s) {
$found = preg_match_all('/\[[zi]mg(.*?)\](.*?)\[/ism',$s,$matches,PREG_SET_ORDER);
if($found) {
foreach($matches as $match) {
foreach($matches as $match) {
$ret[] = [
'href' => $match[2],
'length' => 0,
@ -1754,7 +1794,6 @@ function compat_photos_list($s) {
}
/**
* @brief Create an item for the Atom feed.
*
@ -1766,11 +1805,11 @@ function compat_photos_list($s) {
* @param array $owner
* @param string $comment default false
* @param number $cid default 0
* @param boolean $compat default false
* @return void|string
*/
function atom_entry($item, $type, $author, $owner, $comment = false, $cid = 0, $compat = false) {
if(! $item['parent'])
return;
@ -1922,9 +1961,17 @@ function atom_entry($item, $type, $author, $owner, $comment = false, $cid = 0, $
'abook_id' => $cid,
'entry' => $o
];
/**
* @hooks atom_entry
* * \e array \b item
* * \e string \b type
* * \e array \b author
* * \e array \b owner
* * \e string \b comment
* * \e number \b abook_id
* * \e string \b entry - The generated entry and what will get returned
*/
call_hooks('atom_entry', $x);
return $x['entry'];
}

View file

@ -1,6 +1,7 @@
<?php
/**
* @file include/items.php
* @brief Items related functions.
*/
use Zotlabs\Lib as Zlib;
@ -208,7 +209,7 @@ function is_item_normal($item) {
}
/**
* @brief
* @brief Decide if current observer has sufficient privileges to comment on item.
*
* This function examines the comment_policy attached to an item and decides if the current observer has
* sufficient privileges to comment. This will normally be called on a remote site where perm_is_allowed()
@ -224,10 +225,20 @@ function is_item_normal($item) {
*/
function can_comment_on_post($observer_xchan, $item) {
// logger('can_comment_on_post: comment_policy: ' . $item['comment_policy'], LOGGER_DEBUG);
// logger('Comment_policy: ' . $item['comment_policy'], LOGGER_DEBUG);
$x = [ 'observer_hash' => $observer_xchan, 'item' => $item, 'allowed' => 'unset' ];
call_hooks('can_comment_on_post',$x);
$x = [
'observer_hash' => $observer_xchan,
'item' => $item,
];
/**
* @hooks can_comment_on_post
* Called when deciding whether or not to present a comment box for a post.
* * \e string \b observer_hash
* * \e array \b item
* * \e boolean \b allowed - return value
*/
call_hooks('can_comment_on_post', $x);
if($x['allowed'] !== 'unset')
return $x['allowed'];
@ -386,10 +397,14 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
$_REQUEST['api_source'] = 1;
call_hooks('post_local',$arr);
/**
* @hooks post_local
* Called when an item has been posted on this machine via mod/item.php (also via API).
*/
call_hooks('post_local', $arr);
if(x($arr,'cancel')) {
logger('post_activity_item: post cancelled by plugin.');
if(x($arr, 'cancel')) {
logger('Post cancelled by plugin.');
return $ret;
}
@ -400,6 +415,12 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
$ret['success'] = true;
$ret['item_id'] = $post_id;
$ret['activity'] = $post['item'];
/**
* @hooks post_local_end
* Called after a local post operation has completed.
* * \e array - the item returned from item_store()
*/
call_hooks('post_local_end', $ret['activity']);
}
@ -407,8 +428,8 @@ function post_activity_item($arr, $allow_code = false, $deliver = true) {
Zotlabs\Daemon\Master::Summon(array('Notifier','activity',$post_id));
}
$ret['success'] = true;
return $ret;
}
@ -430,7 +451,6 @@ function validate_item_elements($message,$arr) {
$result['success'] = true;
return $result;
}
@ -469,7 +489,7 @@ function limit_body_size($body) {
if( ($textlen + $img_start) > $maxlen ) {
if($textlen < $maxlen) {
logger('limit_body_size: the limit happens before an embedded image', LOGGER_DEBUG);
logger('The limit happens before an embedded image', LOGGER_DEBUG);
$new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen);
$textlen = $maxlen;
}
@ -799,8 +819,17 @@ function get_item_elements($x,$allow_code = false) {
function import_author_xchan($x) {
$arr = array('xchan' => $x, 'xchan_hash' => '');
call_hooks('import_author_xchan',$arr);
$arr = [
'xchan' => $x,
'xchan_hash' => ''
];
/**
* @hooks import_author_xchan
* Called when looking up an author of a post by xchan_hash to ensure they have an xchan record on our site.
* * \e array \b xchan
* * \e string \b xchan_hash - Thre returned value
*/
call_hooks('import_author_xchan', $arr);
if($arr['xchan_hash'])
return $arr['xchan_hash'];
@ -823,7 +852,6 @@ function import_author_xchan($x) {
}
return($y);
}
/**
@ -835,7 +863,6 @@ function import_author_xchan($x) {
* * \e string \b guid
* @return boolean|string
*/
function import_author_rss($x) {
if(! $x['url'])
return false;
@ -844,7 +871,7 @@ function import_author_rss($x) {
dbesc($x['url'])
);
if($r) {
logger('import_author_rss: in cache' , LOGGER_DEBUG);
logger('In cache' , LOGGER_DEBUG);
return $r[0]['xchan_hash'];
}
$name = trim($x['name']);
@ -883,7 +910,15 @@ function import_author_rss($x) {
function import_author_unknown($x) {
$arr = [ 'author' => $x, 'result' => false ];
$arr = [
'author' => $x,
'result' => false
];
/**
* @hooks import_author
* * \e array \b author
* * \e boolean|string \b result - Return value, default false
*/
call_hooks('import_author', $arr);
if($arr['result'])
return $arr['result'];
@ -895,7 +930,7 @@ function import_author_unknown($x) {
dbesc($x['url'])
);
if($r) {
logger('import_author_unknown: in cache' , LOGGER_DEBUG);
logger('In cache' , LOGGER_DEBUG);
return $r[0]['xchan_hash'];
}
@ -1469,8 +1504,11 @@ function get_profile_elements($x) {
}
/**
* @brief Signs an item body.
*
* @param[in,out] array $item
*/
function item_sign(&$item) {
if(array_key_exists('sig',$item) && $item['sig'])
@ -1483,14 +1521,13 @@ function item_sign(&$item) {
if(! $r)
return;
$item['sig'] = base64url_encode(rsa_sign($item['body'],$r[0]['channel_prvkey']));
$item['sig'] = base64url_encode(rsa_sign($item['body'], $r[0]['channel_prvkey']));
$item['item_verified'] = 1;
}
/**
* @brief
* @brief Stores an item type record.
*
* @param array $arr
* @param boolean $allow_exec (optional) default false
@ -1502,8 +1539,17 @@ function item_sign(&$item) {
*/
function item_store($arr, $allow_exec = false, $deliver = true) {
$d = array('item' => $arr, 'allow_exec' => $allow_exec);
call_hooks('item_store', $d );
$d = [
'item' => $arr,
'allow_exec' => $allow_exec
];
/**
* @hooks item_store
* Called when item_store() stores a record of type item.
* * \e array \b item
* * \e boolean \b allow_exec
*/
call_hooks('item_store', $d);
$arr = $d['item'];
$allow_exec = $d['allow_exec'];
@ -1548,7 +1594,6 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
return $ret;
}
$arr['title'] = ((array_key_exists('title',$arr) && strlen($arr['title'])) ? trim($arr['title']) : '');
$arr['body'] = ((array_key_exists('body',$arr) && strlen($arr['body'])) ? trim($arr['body']) : '');
@ -1566,7 +1611,6 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : 0 );
$arr['lang'] = detect_language($arr['body']);
// apply the input filter here
@ -1581,10 +1625,23 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) {
$translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
$translate = [
'item' => $arr,
'from' => $arr['lang'],
'to' => $allowed_languages,
'translated' => false
];
/**
* @hooks item_translate
* Called from item_store and item_store_update after the post language has been autodetected.
* * \e array \b item
* * \e string \b from
* * \e string \b to
* * \e boolean \b translated
*/
call_hooks('item_translate', $translate);
if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
logger('language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
$ret['message'] = 'language not accepted';
return $ret;
}
@ -1776,18 +1833,26 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
intval($arr['revision'])
);
if($r) {
logger('item_store: duplicate item ignored. ' . print_r($arr,true));
logger('duplicate item ignored. ' . print_r($arr,true));
$ret['message'] = 'duplicate post.';
return $ret;
}
call_hooks('item_store',$arr);
/**
* @hooks item_store
* Called when item_store() stores a record of type item.
*/
call_hooks('item_store', $arr);
// This hook remains for backward compatibility.
call_hooks('post_remote',$arr);
/**
* @hooks post_remote
* Called when an activity arrives from another site.
* This hook remains for backward compatibility.
*/
call_hooks('post_remote', $arr);
if(x($arr,'cancel')) {
logger('item_store: post cancelled by plugin.');
if(x($arr, 'cancel')) {
logger('Post cancelled by plugin.');
$ret['message'] = 'cancelled.';
return $ret;
}
@ -1894,7 +1959,11 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
$ret['item'] = $arr;
call_hooks('post_remote_end',$arr);
/**
* @hooks post_remote_end
* Called after processing a remote post.
*/
call_hooks('post_remote_end', $arr);
// update the commented timestamp on the parent - unless this is potentially a clone of an older item
// which we don't wish to bring to the surface. As the queue only holds deliveries for 3 days, it's
@ -1931,11 +2000,28 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
}
/**
* @brief Update a stored item.
*
* @param array $arr an item
* @param boolean $allow_exec (optional) default false
* @param boolean $deliver (optional) default true
* @return array
*/
function item_store_update($arr, $allow_exec = false, $deliver = true) {
function item_store_update($arr,$allow_exec = false, $deliver = true) {
$d = array('item' => $arr, 'allow_exec' => $allow_exec);
call_hooks('item_store_update', $d );
$d = [
'item' => $arr,
'allow_exec' => $allow_exec
];
/**
* @hooks item_store_update
* Called when item_store_update() is called to update a stored item. It
* overwrites the function's parameters $arr and $allow_exec.
* * \e array \b item
* * \e boolean \b allow_exec
*/
call_hooks('item_store_update', $d);
$arr = $d['item'];
$allow_exec = $d['allow_exec'];
@ -1947,12 +2033,12 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
}
if(! intval($arr['uid'])) {
logger('item_store_update: no uid');
logger('no uid');
$ret['message'] = 'no uid.';
return $ret;
}
if(! intval($arr['id'])) {
logger('item_store_update: no id');
logger('no id');
$ret['message'] = 'no id.';
return $ret;
}
@ -1965,7 +2051,7 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
intval($uid)
);
if(! $orig) {
logger('item_store_update: original post not found: ' . $orig_post_id);
logger('Original post not found: ' . $orig_post_id);
$ret['message'] = 'no original';
return $ret;
}
@ -1997,7 +2083,20 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages');
if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) {
$translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false);
$translate = [
'item' => $arr,
'from' => $arr['lang'],
'to' => $allowed_languages,
'translated' => false
];
/**
* @hooks item_translate
* Called from item_store() and item_store_update() after the post language has been autodetected.
* * \e array \b item - returned value
* * \e string \b from
* * \e string \b to
* * \e boolean \b translated - default false, set true if hook translated it and provide it in item
*/
call_hooks('item_translate', $translate);
if((! $translate['translated']) && (intval(get_pconfig($arr['uid'],'system','reject_disallowed_languages')))) {
logger('item_store: language ' . $arr['lang'] . ' not accepted for uid ' . $arr['uid']);
@ -2097,18 +2196,20 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$arr['item_pending_remove'] = ((array_key_exists('item_pending_remove',$arr)) ? intval($arr['item_pending_remove']) : $orig[0]['item_pending_remove'] );
$arr['item_blocked'] = ((array_key_exists('item_blocked',$arr)) ? intval($arr['item_blocked']) : $orig[0]['item_blocked'] );
$arr['sig'] = ((x($arr,'sig')) ? $arr['sig'] : '');
$arr['layout_mid'] = ((array_key_exists('layout_mid',$arr)) ? dbesc($arr['layout_mid']) : $orig[0]['layout_mid'] );
$arr['public_policy'] = ((x($arr,'public_policy')) ? notags(trim($arr['public_policy'])) : $orig[0]['public_policy'] );
$arr['comment_policy'] = ((x($arr,'comment_policy')) ? notags(trim($arr['comment_policy'])) : $orig[0]['comment_policy'] );
call_hooks('post_remote_update',$arr);
/**
* @hooks post_remote_update
* Called when processing a remote post that involved an edit or update.
*/
call_hooks('post_remote_update', $arr);
if(x($arr,'cancel')) {
logger('item_store_update: post cancelled by plugin.');
if(x($arr, 'cancel')) {
logger('Post cancelled by plugin.');
$ret['message'] = 'cancelled.';
return $ret;
}
@ -2145,9 +2246,9 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$r = dbq("update item set " . $str . " where id = " . $orig_post_id );
if($r)
logger('item_store_update: updated item ' . $orig_post_id, LOGGER_DEBUG);
logger('Updated item ' . $orig_post_id, LOGGER_DEBUG);
else {
logger('item_store_update: could not update item');
logger('Could not update item');
$ret['message'] = 'DB update failed.';
return $ret;
}
@ -2194,7 +2295,11 @@ function item_store_update($arr,$allow_exec = false, $deliver = true) {
$ret['item'] = $arr;
call_hooks('post_remote_update_end',$arr);
/**
* @hooks post_remote_update_end
* Called after processing a remote post that involved an edit or update.
*/
call_hooks('post_remote_update_end', $arr);
if($deliver) {
send_status_notifications($orig_post_id,$arr);
@ -2427,7 +2532,7 @@ function tag_deliver($uid, $item_id) {
}
}
else
logger('tag_deliver: tag permission denied for ' . $u[0]['channel_address']);
logger('Tag permission denied for ' . $u[0]['channel_address']);
}
/*
@ -2463,7 +2568,7 @@ function tag_deliver($uid, $item_id) {
$terms = array_merge(get_terms_oftype($item['term'],TERM_MENTION),get_terms_oftype($item['term'],TERM_FORUM));
if($terms)
logger('tag_deliver: post mentions: ' . print_r($terms,true), LOGGER_DATA);
logger('Post mentions: ' . print_r($terms,true), LOGGER_DATA);
$link = normalise_link($u[0]['xchan_url']);
@ -2477,7 +2582,7 @@ function tag_deliver($uid, $item_id) {
}
if($mention) {
logger('tag_deliver: mention found for ' . $u[0]['channel_name']);
logger('Mention found for ' . $u[0]['channel_name']);
$r = q("update item set item_mentionsme = 1 where id = %d",
intval($item_id)
@ -2543,12 +2648,23 @@ function tag_deliver($uid, $item_id) {
}
if(! ($tagged || $plustagged)) {
logger('tag_deliver: mention was in a reshare or exceeded max_tagged_forums - ignoring');
logger('Mention was in a reshare or exceeded max_tagged_forums - ignoring');
return;
}
$arr = array('channel_id' => $uid, 'item' => $item, 'body' => $body);
call_hooks('tagged',$arr);
$arr = [
'channel_id' => $uid,
'item' => $item,
'body' => $body
];
/**
* @hooks tagged
* Called when a delivery is processed which results in you being tagged.
* * \e number \b channel_id
* * \e array \b item
* * \e string \b body
*/
call_hooks('tagged', $arr);
/*
* Kill two birds with one stone. As long as we're here, send a mention notification.
@ -2567,7 +2683,7 @@ function tag_deliver($uid, $item_id) {
// Just a normal tag?
if(! $plustagged) {
logger('tag_deliver: not a plus tag', LOGGER_DEBUG);
logger('Not a plus tag', LOGGER_DEBUG);
return;
}
@ -2580,7 +2696,7 @@ function tag_deliver($uid, $item_id) {
}
if((! $mention) && (! $union)) {
logger('tag_deliver: no mention for ' . $u[0]['channel_name'] . ' and no union.');
logger('No mention for ' . $u[0]['channel_name'] . ' and no union.');
return;
}
@ -2590,11 +2706,11 @@ function tag_deliver($uid, $item_id) {
if(intval($item['item_wall']) || intval($item['item_origin']) || (! intval($item['item_thread_top'])) || ($item['id'] != $item['parent'])) {
logger('tag_deliver: item was local or a comment. rejected.');
logger('Item was local or a comment. rejected.');
return;
}
logger('tag_deliver: creating second delivery chain.');
logger('Creating second delivery chain.');
start_delivery_chain($u[0],$item,$item_id,null);
}
@ -2605,8 +2721,12 @@ function tag_deliver($uid, $item_id) {
* This is so that the channel with tag_delivery enabled can receive the post even if they turn off
* permissions for the sender to send their stream. tag_deliver() can't be called until the post is actually stored.
* By then it would be too late to reject it.
*
* @param number $uid A chnnel_id
* @param array $item
* @return boolean
*/
function tgroup_check($uid,$item) {
function tgroup_check($uid, $item) {
$mention = false;
@ -2731,8 +2851,8 @@ function start_delivery_chain($channel, $item, $item_id, $parent) {
if($sourced) {
$r = q("select * from source where src_channel_id = %d and ( src_xchan = '%s' or src_xchan = '*' ) limit 1",
intval($channel['channel_id']),
dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan'])
);
dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan'])
);
if($r) {
$t = trim($r[0]['src_tag']);
if($t) {
@ -2741,15 +2861,15 @@ function start_delivery_chain($channel, $item, $item_id, $parent) {
foreach($tags as $tt) {
$tt = trim($tt);
if($tt) {
q("insert into term (uid,oid,otype,ttype,term,url)
values(%d,%d,%d,%d,'%s','%s') ",
intval($channel['channel_id']),
intval($item_id),
intval(TERM_OBJ_POST),
intval(TERM_CATEGORY),
dbesc($tt),
q("insert into term (uid,oid,otype,ttype,term,url)
values(%d,%d,%d,%d,'%s','%s') ",
intval($channel['channel_id']),
intval($item_id),
intval(TERM_OBJ_POST),
intval(TERM_CATEGORY),
dbesc($tt),
dbesc(z_root() . '/channel/' . $channel['channel_address'] . '?f=&cat=' . urlencode($tt))
);
);
}
}
}
@ -3014,7 +3134,6 @@ function mail_store($arr) {
$arr['mail_flags'] = ((x($arr,'mail_flags')) ? intval($arr['mail_flags']) : 0 );
$arr['mail_raw'] = ((x($arr,'mail_raw')) ? intval($arr['mail_raw']) : 0 );
if($arr['parent_mid']) {
$parent_item = q("select * from mail where mid = '%s' and channel_id = %d limit 1",
@ -3022,7 +3141,7 @@ function mail_store($arr) {
intval($arr['channel_id'])
);
if(($parent_item) && (! $arr['conv_guid'])) {
$arr['conv_guid'] = $parent_item[0]['conv_guid'];
$arr['conv_guid'] = $parent_item[0]['conv_guid'];
}
}
else {
@ -3048,19 +3167,23 @@ function mail_store($arr) {
);
if($r) {
logger('mail_store: duplicate item ignored. ' . print_r($arr,true));
logger('Duplicate item ignored. ' . print_r($arr,true));
return 0;
}
if(! $r && $arr['mail_recalled'] == 1) {
logger('mail_store: recalled item not found. ' . print_r($arr,true));
logger('Recalled item not found. ' . print_r($arr,true));
return 0;
}
call_hooks('post_mail',$arr);
/**
* @hooks post_mail
* Called when a mail message has been composed.
*/
call_hooks('post_mail', $arr);
if(x($arr,'cancel')) {
logger('mail_store: post cancelled by plugin.');
logger('Post cancelled by plugin.');
return 0;
}
@ -3077,15 +3200,15 @@ function mail_store($arr) {
if($r) {
$current_post = $r[0]['id'];
logger('mail_store: created item ' . $current_post, LOGGER_DEBUG);
logger('Created item ' . $current_post, LOGGER_DEBUG);
$arr['id'] = $current_post; // for notification
}
else {
logger('mail_store: could not locate created item');
logger('Could not locate created item');
return 0;
}
if(count($r) > 1) {
logger('mail_store: duplicated post occurred. Removing duplicates.');
logger('Duplicated post occurred. Removing duplicates.');
q("DELETE FROM mail WHERE mid = '%s' AND channel_id = %d AND id != %d ",
$arr['mid'],
intval($arr['channel_id']),
@ -3114,7 +3237,11 @@ function mail_store($arr) {
);
}
call_hooks('post_mail_end',$arr);
/**
* @hooks post_mail_end
* Called when a mail message has been delivered.
*/
call_hooks('post_mail_end', $arr);
return $current_post;
}
@ -3135,7 +3262,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) {
$img_st_close++; // make it point to AFTER the closing bracket
$image = substr($orig_body, $img_start + $img_st_close, $img_len);
logger('fix_private_photos: found photo ' . $image, LOGGER_DEBUG);
logger('Found photo ' . $image, LOGGER_DEBUG);
if(stristr($image , $site . '/photo/')) {
// Only embed locally hosted photos
@ -3179,7 +3306,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) {
// If a custom width and height were specified, apply before embedding
if(preg_match("/\[zmg\=([0-9]*)x([0-9]*)\]/is", substr($orig_body, $img_start, $img_st_close), $match)) {
logger('fix_private_photos: scaling photo', LOGGER_DEBUG);
logger('Scaling photo', LOGGER_DEBUG);
$width = intval($match[1]);
$height = intval($match[2]);
@ -3192,9 +3319,9 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) {
}
}
logger('fix_private_photos: replacing photo', LOGGER_DEBUG);
logger('Replacing photo', LOGGER_DEBUG);
$image = 'data:' . $type . ';base64,' . base64_encode($data);
logger('fix_private_photos: replaced: ' . $image, LOGGER_DATA);
logger('Replaced: ' . $image, LOGGER_DATA);
}
}
}
@ -3451,8 +3578,16 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal
);
}
$arr = array('item' => $item, 'interactive' => $interactive, 'stage' => $stage);
call_hooks('drop_item', $arr );
$arr = [
'item' => $item,
'interactive' => $interactive,
'stage' => $stage
];
/**
* @hooks drop_item
* Called when an 'item' is removed.
*/
call_hooks('drop_item', $arr);
$notify_id = intval($item['id']);
@ -3602,8 +3737,14 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) {
return true;
}
function first_post_date($uid,$wall = false) {
/**
* @brief Return the first post date.
*
* @param int $uid
* @param boolean $wall (optional) default false
* @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();
@ -3612,7 +3753,6 @@ function first_post_date($uid,$wall = false) {
where uid = %d and id = parent $item_normal $wall_sql
order by created asc limit 1",
intval($uid)
);
if($r) {
// logger('first_post_date: ' . $r[0]['id'] . ' ' . $r[0]['created'], LOGGER_DATA);
@ -3628,8 +3768,8 @@ function first_post_date($uid,$wall = false) {
* current flat list of all representative dates.
*
* @param int $uid
* @param unknown $wall
* @param unknown $mindate
* @param boolean $wall
* @param string $mindate
* @return array
*/
function list_post_dates($uid, $wall, $mindate) {
@ -3700,8 +3840,14 @@ function posted_dates($uid,$wall) {
return $ret;
}
function fetch_post_tags($items,$link = false) {
/**
* @brief Extend an item array with the associated tags of the posts.
*
* @param array $items
* @param boolean $link (optional) default false
* @return array Return the provided $items array after extended the posts with tags
*/
function fetch_post_tags($items, $link = false) {
$tag_finder = array();
if($items) {
@ -3720,7 +3866,6 @@ function fetch_post_tags($items,$link = false) {
}
$tag_finder_str = implode(', ', $tag_finder);
if(strlen($tag_finder_str)) {
$tags = q("select * from term where oid in ( %s ) and otype = %d",
dbesc($tag_finder_str),
@ -3729,7 +3874,6 @@ function fetch_post_tags($items,$link = false) {
$imeta = q("select * from iconfig where iid in ( %s )",
dbesc($tag_finder_str)
);
}
for($x = 0; $x < count($items); $x ++) {
@ -3779,8 +3923,15 @@ function fetch_post_tags($items,$link = false) {
}
function zot_feed($uid,$observer_hash,$arr) {
/**
* @brief
*
* @param int $uid
* @param string $observer_hash
* @param array $arr
* @return array
*/
function zot_feed($uid, $observer_hash, $arr) {
$result = array();
$mindate = null;
@ -3990,24 +4141,23 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
}
if($arr['search']) {
if(strpos($arr['search'],'#') === 0)
$sql_extra .= term_query('item',substr($arr['search'],1),TERM_HASHTAG,TERM_COMMUNITYTAG);
else
$sql_extra .= sprintf(" AND item.body like '%s' ",
dbesc(protect_sprintf('%' . $arr['search'] . '%'))
);
}
if(strpos($arr['search'],'#') === 0)
$sql_extra .= term_query('item',substr($arr['search'],1),TERM_HASHTAG,TERM_COMMUNITYTAG);
else
$sql_extra .= sprintf(" AND item.body like '%s' ",
dbesc(protect_sprintf('%' . $arr['search'] . '%'))
);
}
if(strlen($arr['file'])) {
$sql_extra .= term_query('item',$arr['files'],TERM_FILE);
}
if(strlen($arr['file'])) {
$sql_extra .= term_query('item',$arr['files'],TERM_FILE);
}
if($arr['conv'] && $channel) {
$sql_extra .= sprintf(" AND parent IN (SELECT distinct parent from item where ( author_xchan like '%s' or item_mentionsme = 1 )) ",
dbesc(protect_sprintf($uidhash))
);
}
if($arr['conv'] && $channel) {
$sql_extra .= sprintf(" AND parent IN (SELECT distinct parent from item where ( author_xchan like '%s' or item_mentionsme = 1 )) ",
dbesc(protect_sprintf($uidhash))
);
}
if (($client_mode & CLIENT_MODE_UPDATE) && (! ($client_mode & CLIENT_MODE_LOAD))) {
// only setup pagination on initial page view
@ -4042,9 +4192,9 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
}
}
$simple_update = (($client_mode & CLIENT_MODE_UPDATE) ? " and item.item_unseen = 1 " : '');
if($client_mode & CLIENT_MODE_LOAD)
$simple_update = '';
$simple_update = (($client_mode & CLIENT_MODE_UPDATE) ? " and item.item_unseen = 1 " : '');
if($client_mode & CLIENT_MODE_LOAD)
$simple_update = '';
//$start = dba_timer();
@ -4087,27 +4237,26 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
if(($client_mode & CLIENT_MODE_LOAD) || ($client_mode == CLIENT_MODE_NORMAL)) {
// Fetch a page full of parent items for this page
// Fetch a page full of parent items for this page
$r = q("SELECT distinct item.id AS item_id, item.$ordering FROM item
left join abook on item.author_xchan = abook.abook_xchan
WHERE $item_uids $item_restrict
AND item.parent = item.id
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_nets
ORDER BY item.$ordering DESC $pager_sql "
);
}
else {
// update
$r = q("SELECT item.parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
WHERE $item_uids $item_restrict $simple_update
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_nets "
);
}
$r = q("SELECT distinct item.id AS item_id, item.$ordering FROM item
left join abook on item.author_xchan = abook.abook_xchan
WHERE $item_uids $item_restrict
AND item.parent = item.id
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_nets
ORDER BY item.$ordering DESC $pager_sql "
);
}
else {
// update
$r = q("SELECT item.parent AS item_id FROM item
left join abook on item.author_xchan = abook.abook_xchan
WHERE $item_uids $item_restrict $simple_update
and (abook.abook_blocked = 0 or abook.abook_flags is null)
$sql_extra3 $sql_extra $sql_nets "
);
}
//$first = dba_timer();
@ -4167,12 +4316,11 @@ function webpage_to_namespace($webpage) {
$page_type = 'docfile';
else
$page_type = 'unknown';
return $page_type;
}
function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remote_id,$mid) {
if(! $post_id)
@ -4296,7 +4444,6 @@ function comment_local_origin($item) {
function send_profile_photo_activity($channel,$photo,$profile) {
// for now only create activities for the default profile
@ -4345,8 +4492,6 @@ function send_profile_photo_activity($channel,$photo,$profile) {
$arr['author_xchan'] = $channel['channel_hash'];
post_activity_item($arr);
}
@ -4549,7 +4694,6 @@ function item_create_edit_activity($post) {
));
$x = post_activity_item($new_item);
$post_id = $x['id'];
@ -4565,5 +4709,4 @@ function item_create_edit_activity($post) {
}
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'edit_activity', $post_id));
}

View file

@ -14,27 +14,25 @@ require_once("include/bbcode.php");
/**
* @brief
* @brief Convert Markdown to bbcode.
*
* We don't want to support a bbcode specific markdown interpreter
* and the markdown library we have is pretty good, but provides HTML output.
* So we'll use that to convert to HTML, then convert the HTML back to bbcode,
* and then clean up a few Diaspora specific constructs.
*
* @param string $s
* @param string $s The message as Markdown
* @param boolean $use_zrl default false
* @return string
* @param array $options default empty
* @return string The message converted to bbcode
*/
function markdown_to_bb($s, $use_zrl = false, $options = []) {
if(is_array($s)) {
btlogger('markdown_to_bb called with array. ' . print_r($s,true), LOGGER_NORMAL, LOG_WARNING);
btlogger('markdown_to_bb called with array. ' . print_r($s, true), LOGGER_NORMAL, LOG_WARNING);
return '';
}
$s = str_replace("&#xD;","\r",$s);
$s = str_replace("&#xD;\n&gt;","",$s);
@ -43,9 +41,18 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) {
// if empty link text replace with the url
$s = preg_replace("/\[\]\((.*?)\)/ism",'[$1]($1)',$s);
$x = [ 'text' => $s , 'zrl' => $use_zrl, 'options' => $options ];
call_hooks('markdown_to_bb_init',$x);
$x = [
'text' => $s,
'zrl' => $use_zrl,
'options' => $options
];
/**
* @hooks markdown_to_bb_init
* * \e string \b text - The message as Markdown and what will get returned
* * \e boolean \b zrl
* * \e array \b options
*/
call_hooks('markdown_to_bb_init', $x);
$s = $x['text'];
@ -67,7 +74,7 @@ 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(array('[img','/img]'),array('[zmg','/zmg]'),$s);
$s = str_replace(['[img', '/img]'], ['[zmg', '/zmg]'], $s);
$s = preg_replace("/([^\]\=]|^)(https?\:\/\/)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]+)/ism", '$1[zrl=$2$3]$2$3[/zrl]',$s);
}
else {
@ -80,13 +87,22 @@ function markdown_to_bb($s, $use_zrl = false, $options = []) {
// Don't show link to full picture (until it is fixed)
$s = scale_external_images($s, false);
call_hooks('markdown_to_bb',$s);
/**
* @hooks markdown_to_bb
* * \e string - The already converted message as bbcode
*/
call_hooks('markdown_to_bb', $s);
return $s;
}
/**
* @brief
*
* @param array $match
* @return string
*/
function bb_to_markdown_share($match) {
$matches = array();
@ -153,17 +169,22 @@ function bb_to_markdown_share($match) {
}
/**
* @brief Convert bbcode to Markdown.
*
* @param string $Text The message as bbcode
* @param array $options default empty
* @return string The message converted to Markdown
*/
function bb_to_markdown($Text, $options = []) {
/*
* Transform #tags, strip off the [url] and replace spaces with underscore
*/
$Text = preg_replace_callback('/#\[([zu])rl\=(.*?)\](.*?)\[\/[(zu)]rl\]/i',
$Text = preg_replace_callback('/#\[([zu])rl\=(.*?)\](.*?)\[\/[(zu)]rl\]/i',
create_function('$match', 'return \'#\'. str_replace(\' \', \'_\', $match[3]);'), $Text);
$Text = preg_replace('/#\^\[([zu])rl\=(.*?)\](.*?)\[\/([zu])rl\]/i', '[$1rl=$2]$3[/$4rl]', $Text);
// Converting images with size parameters to simple images. Markdown doesn't know it.
@ -173,7 +194,12 @@ function bb_to_markdown($Text, $options = []) {
$x = [ 'bbcode' => $Text, 'options' => $options ];
call_hooks('bb_to_markdown_bb',$x);
/**
* @hooks bb_to_markdown_bb
* * \e string \b bbcode - The message as bbcode and what will get returned
* * \e array \b options
*/
call_hooks('bb_to_markdown_bb', $x);
$Text = $x['bbcode'];
@ -202,14 +228,16 @@ function bb_to_markdown($Text, $options = []) {
$Text = trim($Text);
/**
* @hooks bb_to_markdown
* * \e string - The already converted message as bbcode and what will get returned
*/
call_hooks('bb_to_markdown', $Text);
return $Text;
}
/**
* @brief Convert a HTML text into Markdown.
*
@ -217,8 +245,6 @@ function bb_to_markdown($Text, $options = []) {
*
* If the HTML text can not get parsed it will return an empty string.
*
* @see HTMLToMarkdown
*
* @param string $html The HTML code to convert
* @return string Markdown representation of the given HTML text, empty on error
*/
@ -232,8 +258,5 @@ function html2markdown($html) {
logger("Invalid HTML. HTMLToMarkdown library threw an exception.");
}
// The old html 2 markdown library "pixel418/markdownify": "^2.2",
//$md = new HtmlConverter();
//$markdown = $md->convert($Text);
return $markdown;
}

View file

@ -1,6 +1,7 @@
<?php
/**
* @file include/network.php
* @brief Network related functions.
*/
/**
@ -189,7 +190,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
/**
* @brief
* @brief Does a curl post request.
*
* @param string $url
* URL to post
@ -214,7 +215,7 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
* * \e string \b body => content
* * \e string \b debug => from curl_info()
*/
function z_post_url($url,$params, $redirects = 0, $opts = array()) {
function z_post_url($url, $params, $redirects = 0, $opts = array()) {
// logger('url: ' . $url);
// logger('params: ' . print_r($params,true));
@ -276,13 +277,10 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) {
@curl_setopt($ch, CURLOPT_USERPWD, $opts['http_auth']);
}
if(x($opts,'cookiejar'))
@curl_setopt($ch, CURLOPT_COOKIEJAR, $opts['cookiejar']);
if(x($opts,'cookiefile'))
@curl_setopt($ch, CURLOPT_COOKIEFILE, $opts['cookiefile']);
if(x($opts,'cookie'))
@curl_setopt($ch, CURLOPT_COOKIE, $opts['cookie']);
@ -423,7 +421,7 @@ function http_status($val, $msg = '') {
* integer HTTP status result value
* @param string $msg
* optional message
* @return does not return, process is terminated
* @return void does not return, process is terminated
*/
function http_status_exit($val, $msg = '') {
http_status($val, $msg);
@ -431,10 +429,10 @@ function http_status_exit($val, $msg = '') {
}
/**
* @brief convert an XML document to a normalised, case-corrected array used by webfinger.
* @brief Convert an XML document to a normalised, case-corrected array used by webfinger.
*
* @param string|array|SimpleXMLElement $xml_element
* @param int $recursion_depth[in,out]
* @param[in,out] int $recursion_depth
* @return NULL|string|array
*/
function convert_xml_element_to_array($xml_element, &$recursion_depth=0) {
@ -501,14 +499,14 @@ function z_dns_check($h,$check_mx = 0) {
}
/**
* @brief Validates a given URL
* @brief Validates a given URL.
*
* Take a URL from the wild, prepend http:// if necessary and check DNS to see
* if it's real (or check if is a valid IP address).
*
* @see z_dns_check()
*
* @param string $url[in,out] URL to check
* @param[in,out] string $url URL to check
* @return boolean Return true if it's OK, false if something is wrong with it
*/
function validate_url(&$url) {
@ -593,6 +591,7 @@ function allowed_url($url) {
}
}
}
return $found;
}
@ -658,7 +657,7 @@ function allowed_email($email) {
function parse_xml_string($s,$strict = true) {
function parse_xml_string($s, $strict = true) {
if($strict) {
if(! strstr($s,'<?xml'))
return false;
@ -683,14 +682,21 @@ function parse_xml_string($s,$strict = true) {
return $x;
}
/**
* @brief Scales an external image.
*
* @param string $s
* @param string $include_link default true
* @param string $scale_replace default false
* @return string
*/
function scale_external_images($s, $include_link = true, $scale_replace = false) {
// Picture addresses can contain special characters
$s = htmlspecialchars_decode($s, ENT_COMPAT);
$matches = null;
$c = preg_match_all('/\[([zi])mg(.*?)\](.*?)\[\/[zi]mg\]/ism',$s,$matches,PREG_SET_ORDER);
$c = preg_match_all('/\[([zi])mg(.*?)\](.*?)\[\/[zi]mg\]/ism', $s, $matches, PREG_SET_ORDER);
if($c) {
require_once('include/photo/photo_driver.php');
@ -717,22 +723,21 @@ function scale_external_images($s, $include_link = true, $scale_replace = false)
else
$scaled = $mtch[3];
if(! strpbrk(substr($scaled,0,1),'zhfmt'))
if(! strpbrk(substr($scaled, 0, 1), 'zhfmt'))
continue;
$i = z_fetch_url($scaled,true);
$i = z_fetch_url($scaled, true);
$cache = get_config('system','itemcache');
$cache = get_config('system', 'itemcache');
if (($cache != '') and is_dir($cache)) {
$cachefile = $cache."/".hash("md5", $scaled);
$cachefile = $cache . '/' . hash('md5', $scaled);
file_put_contents($cachefile, $i['body']);
}
// guess mimetype from headers or filename
$type = guess_image_type($mtch[3],$i['header']);
if(strpos($type,'image') === false)
$type = guess_image_type($mtch[3], $i['header']);
if(strpos($type, 'image') === false)
continue;
if($i['success']) {
@ -764,7 +769,7 @@ function scale_external_images($s, $include_link = true, $scale_replace = false)
// replace the special char encoding
$s = htmlspecialchars($s,ENT_COMPAT,'UTF-8');
$s = htmlspecialchars($s, ENT_COMPAT, 'UTF-8');
return $s;
}
@ -1141,7 +1146,14 @@ function discover_by_url($url, $arr = null) {
return true;
}
function discover_by_webbie($webbie,$protocol = '') {
/**
* @brief
*
* @param string $webbie
* @param string $protocol (optional) default empty
* @return boolean
*/
function discover_by_webbie($webbie, $protocol = '') {
$result = [];
@ -1149,7 +1161,7 @@ function discover_by_webbie($webbie,$protocol = '') {
// $webbie = strtolower($webbie);
$x = webfinger_rfc7033($webbie,true);
$x = webfinger_rfc7033($webbie, true);
if($x && array_key_exists('links',$x) && $x['links']) {
foreach($x['links'] as $link) {
if(array_key_exists('rel',$link)) {
@ -1158,7 +1170,7 @@ function discover_by_webbie($webbie,$protocol = '') {
// here.
if($link['rel'] === PROTOCOL_ZOT && ((! $protocol) || (strtolower($protocol) === 'zot'))) {
logger('discover_by_webbie: zot found for ' . $webbie, LOGGER_DEBUG);
logger('zot found for ' . $webbie, LOGGER_DEBUG);
if(array_key_exists('zot',$x) && $x['zot']['success']) {
$i = import_xchan($x['zot']);
return true;
@ -1178,16 +1190,35 @@ function discover_by_webbie($webbie,$protocol = '') {
logger('webfinger: ' . print_r($x,true), LOGGER_DATA, LOG_INFO);
$arr = array('address' => $webbie, 'protocol' => $protocol, 'success' => false, 'webfinger' => $x);
$arr = [
'address' => $webbie,
'protocol' => $protocol,
'success' => false,
'webfinger' => $x
];
/**
* @hooks discover_channel_webfinger
* Called when performing a webfinger lookup.
* * \e string \b address - The webbie
* * \e string \b protocol
* * \e array \b webfinger - The result from webfinger_rfc7033()
* * \e boolean \b success - The return value, default false
*/
call_hooks('discover_channel_webfinger', $arr);
if($arr['success'])
return true;
return false;
}
function webfinger_rfc7033($webbie,$zot = false) {
/**
* @brief Fetch and return a webfinger for a webbie.
*
* @param string $webbie - The webbie
* @param boolean $zot (optional) default false
* @return boolean|string false or associative array from result JSON
*/
function webfinger_rfc7033($webbie, $zot = false) {
if(strpos($webbie,'@')) {
$lhs = substr($webbie,0,strpos($webbie,'@'));
@ -1199,6 +1230,7 @@ function webfinger_rfc7033($webbie,$zot = false) {
if($m) {
if($m['scheme'] !== 'https')
return false;
$rhs = $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
$resource = urlencode($webbie);
}
@ -1211,20 +1243,19 @@ function webfinger_rfc7033($webbie,$zot = false) {
// and results in a 406 (Not Acceptable) response, and will also incorrectly produce an XML
// document if you use 'application/jrd+json, */*'. We could set this to application/jrd+json,
// but some test webfinger servers may not explicitly set the content type and they would be
// blocked. The best compromise until Mastodon is fixed is to remove the Accept header which is
// accomplished by setting it to nothing.
// blocked. The best compromise until Mastodon is fixed is to remove the Accept header which is
// accomplished by setting it to nothing.
$counter = 0;
$s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''),
$s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''),
false, $counter, [ 'headers' => [ 'Accept:' ] ]);
if($s['success']) {
$j = json_decode($s['body'],true);
$j = json_decode($s['body'], true);
return($j);
}
return false;
}
function old_webfinger($webbie) {
@ -1604,7 +1635,13 @@ function check_siteallowed($url) {
$retvalue = true;
$arr = array('url' => $url);
call_hooks('check_siteallowed',$arr);
/**
* @hooks check_siteallowed
* Used to over-ride or bypass the site black/white block lists.
* * \e string \b url
* * \e boolean \b allowed - optional return value set in hook
*/
call_hooks('check_siteallowed', $arr);
if(array_key_exists('allowed',$arr))
return $arr['allowed'];
@ -1643,7 +1680,13 @@ function check_channelallowed($hash) {
$retvalue = true;
$arr = array('hash' => $hash);
call_hooks('check_channelallowed',$arr);
/**
* @hooks check_channelallowed
* Used to over-ride or bypass the channel black/white block lists.
* * \e string \b hash
* * \e boolean \b allowed - optional return value set in hook
*/
call_hooks('check_channelallowed', $arr);
if(array_key_exists('allowed',$arr))
return $arr['allowed'];
@ -1732,6 +1775,10 @@ function network_to_name($s) {
NETWORK_MYSPACE => t('MySpace'),
);
/**
* @hooks network_to_name
* @deprecated
*/
call_hooks('network_to_name', $nets);
$search = array_keys($nets);
@ -1743,7 +1790,7 @@ function network_to_name($s) {
/**
* @brief Send a text email message.
*
* @param array $params an assoziative array with:
* @param array $params an associative array with:
* * \e string \b fromName name of the sender
* * \e string \b fromEmail email of the sender
* * \e string \b replyTo replyTo address to direct responses
@ -1774,6 +1821,10 @@ function z_mail($params) {
$params['sent'] = false;
$params['result'] = false;
/**
* @hooks email_send
* * \e params @see z_mail()
*/
call_hooks('email_send', $params);
if($params['sent']) {
@ -1921,60 +1972,78 @@ function service_plink($contact, $guid) {
$plink = $url . '/channel/' . $handle . '?f=&mid=' . $guid;
$x = [ 'xchan' => $contact, 'guid' => $guid, 'url' => $url, 'plink' => $plink ];
/**
* @hooks service_plink
* * \e array \b xchan
* * \e string \b guid
* * \e string \b url
* * \e string \b plink will get returned
*/
call_hooks('service_plink', $x);
return $x['plink'];
}
/**
* @brief
*
* @param array $mimeTypes
* @param string $acceptedTypes by default false will use $_SERVER['HTTP_ACCEPT']
* @return array|NULL
*/
function getBestSupportedMimeType($mimeTypes = null, $acceptedTypes = false) {
// Values will be stored in this array
// Values will be stored in this array
$AcceptTypes = [];
if($acceptedTypes === false)
$acceptedTypes = $_SERVER['HTTP_ACCEPT'];
$AcceptTypes = Array ();
// Accept header is case insensitive, and whitespace isnt important
$accept = strtolower(str_replace(' ', '', $acceptedTypes));
// divide it into parts in the place of a ","
$accept = explode(',', $accept);
foreach ($accept as $a) {
// the default quality is 1.
$q = 1;
// check if there is a different quality
if (strpos($a, ';q=')) {
// divide "mime/type;q=X" into two parts: "mime/type" i "X"
list($a, $q) = explode(';q=', $a);
}
// mime-type $a is accepted with the quality $q
// WARNING: $q == 0 means, that mime-type isnt supported!
$AcceptTypes[$a] = $q;
}
arsort($AcceptTypes);
// Accept header is case insensitive, and whitespace isnt important
$accept = strtolower(str_replace(' ', '', $acceptedTypes));
// divide it into parts in the place of a ","
$accept = explode(',', $accept);
foreach ($accept as $a) {
// the default quality is 1.
$q = 1;
// check if there is a different quality
if (strpos($a, ';q=')) {
// divide "mime/type;q=X" into two parts: "mime/type" i "X"
list($a, $q) = explode(';q=', $a);
}
// mime-type $a is accepted with the quality $q
// WARNING: $q == 0 means, that mime-type isnt supported!
$AcceptTypes[$a] = $q;
}
arsort($AcceptTypes);
// if no parameter was passed, just return parsed data
if (!$mimeTypes) return $AcceptTypes;
// if no parameter was passed, just return parsed data
if (!$mimeTypes) return $AcceptTypes;
$mimeTypes = array_map('strtolower', (array)$mimeTypes);
$mimeTypes = array_map('strtolower', (array)$mimeTypes);
// lets check our supported types:
foreach ($AcceptTypes as $mime => $q) {
if ($q && in_array($mime, $mimeTypes)) return $mime;
}
// lets check our supported types:
foreach ($AcceptTypes as $mime => $q) {
if ($q && in_array($mime, $mimeTypes)) return $mime;
}
// no mime-type found
return null;
// no mime-type found
return null;
}
/**
* @brief Perform caching for jsonld normaliser.
*
* @param string $url
* @return mixed|boolean|array
*/
function jsonld_document_loader($url) {
// perform caching for jsonld normaliser
require_once('library/jsonld/jsonld.php');
$cachepath = 'store/[data]/ldcache';
if(! is_dir($cachepath))
os_mkdir($cachepath,STORAGE_DEFAULT_PERMISSIONS,true);
os_mkdir($cachepath, STORAGE_DEFAULT_PERMISSIONS, true);
$filename = $cachepath . '/' . urlencode($url);
if(file_exists($filename) && filemtime($filename) > time() - (12 * 60 * 60)) {
@ -1983,7 +2052,7 @@ function jsonld_document_loader($url) {
$r = jsonld_default_document_loader($url);
if($r) {
file_put_contents($filename,json_encode($r));
file_put_contents($filename, json_encode($r));
return $r;
}
@ -1993,5 +2062,4 @@ function jsonld_document_loader($url) {
}
return [];
}

View file

@ -10,14 +10,13 @@ require_once('include/photo/photo_driver.php');
require_once('include/text.php');
/**
* @brief
* @brief Upload a photo.
*
* @param array $channel
* @param array $observer
* @param array $args
* @return array
*/
function photo_upload($channel, $observer, $args) {
$ret = array('success' => false);
@ -115,25 +114,33 @@ function photo_upload($channel, $observer, $args) {
if (! $type)
$type=guess_image_type($filename);
logger('photo_upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG);
logger('Received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG);
$maximagesize = get_config('system','maximagesize');
if (($maximagesize) && ($filesize > $maximagesize)) {
$ret['message'] = sprintf ( t('Image exceeds website size limit of %lu bytes'), $maximagesize);
@unlink($src);
call_hooks('photo_upload_end',$ret);
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
*/
call_hooks('photo_upload_end', $ret);
return $ret;
}
if (! $filesize) {
$ret['message'] = t('Image file is empty.');
@unlink($src);
call_hooks('photo_post_end',$ret);
/**
* @hooks photo_post_end
* Called after uploading a photo.
*/
call_hooks('photo_post_end', $ret);
return $ret;
}
logger('photo_upload: loading the contents of ' . $src , LOGGER_DEBUG);
logger('Loading the contents of ' . $src , LOGGER_DEBUG);
$imagedata = @file_get_contents($src);
}
@ -146,7 +153,11 @@ function photo_upload($channel, $observer, $args) {
if (($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) {
$ret['message'] = upgrade_message();
@unlink($src);
call_hooks('photo_post_end',$ret);
/**
* @hooks photo_post_end
* Called after uploading a photo.
*/
call_hooks('photo_post_end', $ret);
return $ret;
}
@ -154,9 +165,13 @@ function photo_upload($channel, $observer, $args) {
if (! $ph->is_valid()) {
$ret['message'] = t('Unable to process image');
logger('photo_upload: unable to process image');
logger('unable to process image');
@unlink($src);
call_hooks('photo_upload_end',$ret);
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
*/
call_hooks('photo_upload_end', $ret);
return $ret;
}
@ -266,8 +281,12 @@ function photo_upload($channel, $observer, $args) {
intval($channel_id)
);
$ret['message'] = t('Photo storage failed.');
logger('photo_upload: photo store failed.');
call_hooks('photo_upload_end',$ret);
logger('Photo store failed.');
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
*/
call_hooks('photo_upload_end', $ret);
return $ret;
}
@ -293,8 +312,6 @@ function photo_upload($channel, $observer, $args) {
$width = $link[1]['width'];
$height = $link[1]['height'];
$tag = (($r1) ? '[zmg=' . $width . 'x' . $height . ']' : '[zmg]');
}
else {
$scale = 2;
@ -352,7 +369,6 @@ function photo_upload($channel, $observer, $args) {
$item['target'] = json_encode($target);
$force = true;
}
$r = q("select id, edited from item where mid = '%s' and uid = %d limit 1",
dbesc($item['mid']),
@ -420,7 +436,6 @@ function photo_upload($channel, $observer, $args) {
$arr['item_private'] = 1;
$result = item_store($arr,false,$deliver);
$item_id = $result['item_id'];
@ -434,7 +449,11 @@ function photo_upload($channel, $observer, $args) {
$ret['resource_id'] = $photo_hash;
$ret['photoitem_id'] = $item_id;
call_hooks('photo_upload_end',$ret);
/**
* @hooks photo_upload_end
* Called when a photo upload has been processed.
*/
call_hooks('photo_upload_end', $ret);
return $ret;
}
@ -499,10 +518,8 @@ function photo_calculate_1600_scale($arr) {
}
return $dest_width . 'x' . $dest_height;
}
/**
* @brief Returns a list with all photo albums observer is allowed to see.
*
@ -517,7 +534,6 @@ function photo_calculate_1600_scale($arr) {
* * \e boolean \b success
* * \e array \b albums
*/
function photos_albums_list($channel, $observer, $sort_key = 'display_path', $direction = 'asc') {
$channel_id = $channel['channel_id'];
@ -610,14 +626,13 @@ function photos_album_widget($channelx,$observer,$sortkey = 'display_path',$dire
}
/**
* @brief
* @brief Return an array of photos.
*
* @param array $channel
* @param array $observer
* @param string $album default empty
* @param string $album (optional) default empty
* @return boolean|array
*/
function photos_list_photos($channel, $observer, $album = '') {
$channel_id = $channel['channel_id'];
@ -654,21 +669,20 @@ function photos_list_photos($channel, $observer, $album = '') {
* @brief Check if given photo album exists in channel.
*
* @param int $channel_id id of the channel
* @param string $observer_hash
* @param string $album name of the album
* @return boolean
*/
function photos_album_exists($channel_id, $observer_hash, $album) {
$sql_extra = permissions_sql($channel_id,$observer_hash);
$sql_extra = permissions_sql($channel_id, $observer_hash);
$r = q("SELECT folder, hash, is_dir, filename, os_path, display_path FROM attach WHERE hash = '%s' AND is_dir = 1 AND uid = %d $sql_extra limit 1",
dbesc($album),
intval($channel_id)
);
// partial backward compatibility with Hubzilla < 2.4 when we used the filename only
// partial backward compatibility with Hubzilla < 2.4 when we used the filename only
// (ambiguous which would get chosen if you had two albums of the same name in different directories)
if(!$r && ctype_xdigit($album)) {
$r = q("SELECT folder, hash, is_dir, filename, os_path, display_path FROM attach WHERE filename = '%s' AND is_dir = 1 AND uid = %d $sql_extra limit 1",
@ -690,7 +704,6 @@ function photos_album_exists($channel_id, $observer_hash, $album) {
* @param string $newname The new name of the album
* @return bool|array
*/
function photos_album_rename($channel_id, $oldname, $newname) {
return q("UPDATE photo SET album = '%s' WHERE album = '%s' AND uid = %d",
dbesc($newname),
@ -699,17 +712,14 @@ function photos_album_rename($channel_id, $oldname, $newname) {
);
}
/**
* @brief
*
* @param int $channel_id
* @param string $album
* @param string $remote_xchan
* @param string $remote_xchan (optional) default empty
* @return string|boolean
*/
function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') {
if($remote_xchan) {
@ -743,15 +753,13 @@ function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') {
* @param array $channel
* @param string $creator_hash
* @param array $photo
* @param boolean $visible default false
* @param boolean $visible (optional) default false
* @return int item_id
*/
function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
// Create item container
$item_hidden = (($visible) ? 0 : 1 );
$mid = item_message_id();
@ -791,36 +799,36 @@ function photos_create_item($channel, $creator_hash, $photo, $visible = false) {
function getGps($exifCoord, $hemi) {
$degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
$minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
$seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;
$degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
$minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
$seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;
$flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1;
$flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1;
return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600)));
return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600)));
}
function getGpstimestamp($exifCoord) {
$hours = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
$minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
$seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;
$hours = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0;
$minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0;
$seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0;
return sprintf('%02d:%02d:%02d',$hours,$minutes,$seconds);
return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
}
function gps2Num($coordPart) {
$parts = explode('/', $coordPart);
$parts = explode('/', $coordPart);
if (count($parts) <= 0)
return 0;
if (count($parts) <= 0)
return 0;
if (count($parts) == 1)
return $parts[0];
if (count($parts) == 1)
return $parts[0];
return floatval($parts[0]) / floatval($parts[1]);
return floatval($parts[0]) / floatval($parts[1]);
}
@ -832,7 +840,7 @@ function photo_profile_setperms($channel_id,$resource_id,$profile_id) {
$r = q("select profile_guid, is_default from profile where id = %d and uid = %d limit 1",
dbesc($profile_id),
intval($channel_id)
);
);
if(! $r)
return;
@ -841,26 +849,26 @@ function photo_profile_setperms($channel_id,$resource_id,$profile_id) {
$profile_guid = $r[0]['profile_guid'];
if($is_default) {
$r = q("update photo set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = ''
$r = q("update photo set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = ''
where resource_id = '%s' and uid = %d",
dbesc($resource_id),
intval($channel_id)
);
$r = q("update attach set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = ''
$r = q("update attach set allow_cid = '', allow_gid = '', deny_cid = '', deny_gid = ''
where hash = '%s' and uid = %d",
dbesc($resource_id),
intval($channel_id)
);
}
else {
$r = q("update photo set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = ''
$r = q("update photo set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = ''
where resource_id = '%s' and uid = %d",
dbesc('<vp.' . $profile_guid . '>'),
dbesc($resource_id),
intval($channel_id)
);
$r = q("update attach set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = ''
$r = q("update attach set allow_cid = '', allow_gid = '%s', deny_cid = '', deny_gid = ''
where hash = '%s' and uid = %d",
dbesc('<vp.' . $profile_guid . '>'),
dbesc($resource_id),
@ -869,71 +877,72 @@ function photo_profile_setperms($channel_id,$resource_id,$profile_id) {
}
}
/**
* @brief
*
* @param int $uid
* @param int|string $profileid
*/
function profile_photo_set_profile_perms($uid, $profileid = 0) {
$allowcid = '';
if($profileid) {
$r = q("SELECT photo, profile_guid, id, is_default, uid
FROM profile WHERE uid = %d and ( profile.id = %d OR profile.profile_guid = '%s') LIMIT 1",
intval($uid),
intval($profileid),
dbesc($profileid)
);
}
else {
logger('Resetting permissions on default-profile-photo for user'.local_channel());
$r = q("SELECT photo, profile_guid, id, is_default, uid
FROM profile WHERE uid = %d and ( profile.id = %d OR profile.profile_guid = '%s') LIMIT 1",
intval($uid),
intval($profileid),
dbesc($profileid)
$r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile
WHERE profile.uid = %d AND is_default = 1 LIMIT 1",
intval($uid)
); //If no profile is given, we update the default profile
}
if(! $r)
return;
$profile = $r[0];
if($profile['id'] && $profile['photo']) {
preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
$resource_id = $resource_id[0];
if (! intval($profile['is_default'])) {
$r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1",
intval($uid)
);
//Should not be needed in future. Catches old int-profile-ids.
$r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ",
intval($profile['id'])
);
$r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'",
dbesc($profile['profile_guid'])
);
$allowcid = "<" . $r0[0]['channel_hash'] . ">";
foreach ($r1 as $entry) {
$allowcid .= "<" . $entry['abook_xchan'] . ">";
}
foreach ($r2 as $entry) {
$allowcid .= "<" . $entry['abook_xchan'] . ">";
}
q("UPDATE photo SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",
dbesc($allowcid),
dbesc($resource_id),
intval($uid)
);
}
else {
logger('Resetting permissions on default-profile-photo for user'.local_channel());
$r = q("SELECT photo, profile_guid, id, is_default, uid FROM profile
WHERE profile.uid = %d AND is_default = 1 LIMIT 1",
//Reset permissions on default profile picture to public
q("UPDATE photo SET allow_cid = '' WHERE photo_usage = %d AND uid = %d",
intval(PHOTO_PROFILE),
intval($uid)
); //If no profile is given, we update the default profile
);
}
if(! $r)
return;
$profile = $r[0];
if($profile['id'] && $profile['photo']) {
preg_match("@\w*(?=-\d*$)@i", $profile['photo'], $resource_id);
$resource_id = $resource_id[0];
if (! intval($profile['is_default'])) {
$r0 = q("SELECT channel_hash FROM channel WHERE channel_id = %d LIMIT 1",
intval($uid)
);
//Should not be needed in future. Catches old int-profile-ids.
$r1 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%d' ",
intval($profile['id'])
);
$r2 = q("SELECT abook.abook_xchan FROM abook WHERE abook_profile = '%s'",
dbesc($profile['profile_guid'])
);
$allowcid = "<" . $r0[0]['channel_hash'] . ">";
foreach ($r1 as $entry) {
$allowcid .= "<" . $entry['abook_xchan'] . ">";
}
foreach ($r2 as $entry) {
$allowcid .= "<" . $entry['abook_xchan'] . ">";
}
q("UPDATE photo SET allow_cid = '%s' WHERE resource_id = '%s' AND uid = %d",
dbesc($allowcid),
dbesc($resource_id),
intval($uid)
);
}
else {
//Reset permissions on default profile picture to public
q("UPDATE photo SET allow_cid = '' WHERE photo_usage = %d AND uid = %d",
intval(PHOTO_PROFILE),
intval($uid)
);
}
}
return;
}
}

View file

@ -7,7 +7,7 @@
/**
* @brief unloads an addon.
* @brief Unloads an addon.
*
* @param string $plugin name of the addon
*/
@ -22,7 +22,7 @@ function unload_plugin($plugin){
}
/**
* @brief uninstalls an addon.
* @brief Uninstalls an addon.
*
* @param string $plugin name of the addon
* @return boolean
@ -110,6 +110,13 @@ function load_plugin($plugin) {
}
}
/**
* @brief Check if addon is installed.
*
* @param string $name
* @return boolean
*/
function plugin_is_installed($name) {
$r = q("select aname from addon where aname = '%s' and installed = 1 limit 1",
dbesc($name)
@ -121,8 +128,9 @@ function plugin_is_installed($name) {
}
// reload all updated plugins
/**
* @brief Reload all updated plugins.
*/
function reload_plugins() {
$plugins = get_config('system', 'addon');
if(strlen($plugins)) {
@ -167,13 +175,18 @@ function reload_plugins() {
}
}
/**
* @brief Get a list of non hidden addons.
*
* @return array
*/
function visible_plugin_list() {
$r = q("select * from addon where hidden = 0 order by aname asc");
return(($r) ? ids_to_array($r,'aname') : array());
}
/**
* @brief registers a hook.
*
@ -282,7 +295,7 @@ function insert_hook($hook, $fn, $version = 0, $priority = 0) {
* the provided data.
*
* @param string $name of the hook to call
* @param string|array &$data to transmit to the callback handler
* @param[in,out] string|array &$data to transmit to the callback handler
*/
function call_hooks($name, &$data = null) {
$a = 0;
@ -414,8 +427,8 @@ function check_plugin_versions($info) {
|| stristr($info['serverroles'],'any')
|| stristr($info['serverroles'],$role))) {
logger('serverrole limit: ' . $info['name'],LOGGER_NORMAL,LOG_WARNING);
return false;
return false;
}
}
@ -447,8 +460,6 @@ function check_plugin_versions($info) {
}
/**
* @brief Parse theme comment in search of theme infos.
*
@ -532,7 +543,7 @@ function get_theme_info($theme){
*
* The screenshot is expected as view/theme/$theme/img/screenshot.[png|jpg].
*
* @param sring $theme The name of the theme
* @param string $theme The name of the theme
* @return string
*/
function get_theme_screenshot($theme) {
@ -626,15 +637,16 @@ function format_css_if_exists($source) {
}
}
/*
/**
* This basically calculates the baseurl. We have other functions to do that, but
* there was an issue with script paths and mixed-content whose details are arcane
* and perhaps lost in the message archives. The short answer is that we're ignoring
* the URL which we are "supposed" to use, and generating script paths relative to
* the URL which we are currently using; in order to ensure they are found and aren't
* blocked due to mixed content issues.
*
* @return string
*/
function script_path() {
if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS'])
$scheme = 'https';
@ -659,6 +671,7 @@ function script_path() {
else {
return z_root();
}
return $scheme . '://' . $hostname;
}
@ -675,10 +688,13 @@ function head_remove_js($src, $priority = 0) {
unset(App::$js_sources[$priority][$index]);
}
// We should probably try to register main.js with a high priority, but currently we handle it
// separately and put it at the end of the html head block in case any other javascript is
// added outside the head_add_js construct.
/**
* We should probably try to register main.js with a high priority, but currently
* we handle it separately and put it at the end of the html head block in case
* any other javascript is added outside the head_add_js construct.
*
* @return string
*/
function head_get_js() {
$str = '';
@ -694,6 +710,7 @@ function head_get_js() {
}
}
}
return $str;
}
@ -703,6 +720,7 @@ function head_get_main_js() {
if(count($sources))
foreach($sources as $source)
$str .= format_js_if_exists($source,true);
return $str;
}
@ -716,7 +734,7 @@ function format_js_if_exists($source) {
if(substr($source,0,2) === '//') {
$path_prefix = '';
}
}
}
else {
// It's a file from the theme
$path = '/' . theme_include($source);
@ -781,12 +799,16 @@ function get_markup_template($s, $root = '') {
return $template;
}
/**
* @brief
*
* @param string $folder
* @return boolean|string
*/
function folder_exists($folder) {
// Get canonicalized absolute pathname
$path = realpath($folder);
function folder_exists($folder)
{
// Get canonicalized absolute pathname
$path = realpath($folder);
// If it exist, check if it's a directory
return (($path !== false) && is_dir($path)) ? $path : false;
// If it exist, check if it's a directory
return (($path !== false) && is_dir($path)) ? $path : false;
}

View file

@ -21,6 +21,7 @@ function is_matrix_url($url) {
}
$remembered[$m['host']] = false;
}
return false;
}
@ -32,14 +33,8 @@ function is_matrix_url($url) {
* @param boolean $address
* $address to use instead of session environment
* @return string
*
* @hooks 'zid'
* string url - url to accept zid
* string zid - urlencoded zid
* string result - the return string we calculated, change it if you want to return something else
*/
function zid($s,$address = '') {
function zid($s, $address = '') {
if (! strlen($s) || strpos($s,'zid='))
return $s;
@ -74,7 +69,18 @@ function zid($s,$address = '') {
if($fragment)
$zurl .= '#' . $fragment;
$arr = array('url' => $s, 'zid' => urlencode($myaddr), 'result' => $zurl);
$arr = [
'url' => $s,
'zid' => urlencode($myaddr),
'result' => $zurl
];
/**
* @hooks zid
* Called when adding the observer's zid to a URL.
* * \e string \b url - url to accept zid
* * \e string \b zid - urlencoded zid
* * \e string \b result - the return string we calculated, change it if you want to return something else
*/
call_hooks('zid', $arr);
return $arr['result'];
@ -100,25 +106,26 @@ function strip_zats($s) {
* because the latter is used for general purpose conversions and the former is used only when preparing text for
* immediate display.
*
* Issues: Currently the order of HTML parameters in the text is somewhat rigid and inflexible.
* @TODO Issues: Currently the order of HTML parameters in the text is somewhat rigid and inflexible.
* We assume it looks like \<a class="zrl" href="xxxxxxxxxx"\> and will not work if zrl and href appear in a different order.
*
* @param array $match
* @return string
*/
function zidify_callback($match) {
$is_zid = ((feature_enabled(local_channel(),'sendzid')) || (strpos($match[1],'zrl')) ? true : false);
$is_zid = ((feature_enabled(local_channel(), 'sendzid')) || (strpos($match[1], 'zrl')) ? true : false);
$replace = '<a' . $match[1] . ' href="' . (($is_zid) ? zid($match[2]) : $match[2]) . '"';
$x = str_replace($match[0],$replace,$match[0]);
$x = str_replace($match[0], $replace, $match[0]);
return $x;
}
function zidify_img_callback($match) {
$is_zid = ((feature_enabled(local_channel(),'sendzid')) || (strpos($match[1],'zrl')) ? true : false);
$is_zid = ((feature_enabled(local_channel(), 'sendzid')) || (strpos($match[1], 'zrl')) ? true : false);
$replace = '<img' . $match[1] . ' src="' . (($is_zid) ? zid($match[2]) : $match[2]) . '"';
$x = str_replace($match[0],$replace,$match[0]);
$x = str_replace($match[0], $replace, $match[0]);
return $x;
}
@ -132,12 +139,11 @@ function zidify_links($s) {
}
function zidify_text_callback($match) {
$is_zid = is_matrix_url($match[2]);
$replace = '<a' . $match[1] . ' href="' . (($is_zid) ? zid($match[2]) : $match[2]) . '"';
$x = str_replace($match[0],$replace,$match[0]);
$x = str_replace($match[0], $replace, $match[0]);
return $x;
}
@ -146,7 +152,7 @@ function zidify_text_img_callback($match) {
$is_zid = is_matrix_url($match[2]);
$replace = '<img' . $match[1] . ' src="' . (($is_zid) ? zid($match[2]) : $match[2]) . '"';
$x = str_replace($match[0],$replace,$match[0]);
$x = str_replace($match[0], $replace, $match[0]);
return $x;
}
@ -157,8 +163,6 @@ function zidify_text($s) {
$s = preg_replace_callback('/\<img(.*?)src\=\"(.*?)\"/ism','zidify_text_img_callback',$s);
return $s;
}
@ -198,7 +202,6 @@ function red_zrl_callback($matches) {
* @param array $matches
* @return string
*/
function red_escape_zrl_callback($matches) {
// Uncertain why the url/zrl forms weren't picked up by the non-greedy regex.
@ -234,11 +237,17 @@ function red_zrlify_img_callback($matches) {
return $matches[0];
}
/**
* @brief OpenWebAuth authentication.
*
* @param string $token
*/
function owt_init($token) {
\Zotlabs\Zot\Verify::purge('owt','3 MINUTE');
\Zotlabs\Zot\Verify::purge('owt', '3 MINUTE');
$ob_hash = \Zotlabs\Zot\Verify::get_meta('owt',0,$token);
$ob_hash = \Zotlabs\Zot\Verify::get_meta('owt', 0, $token);
if($ob_hash === false) {
return;
@ -262,7 +271,7 @@ function owt_init($token) {
}
if(! $r) {
logger('owt: unable to finger ' . $ob_hash);
return;
return;
}
$hubloc = $r[0];
@ -296,14 +305,25 @@ function owt_init($token) {
$_SESSION['DNT'] = 1;
}
$arr = array('xchan' => $hubloc, 'url' => \App::$query_string, 'session' => $_SESSION);
call_hooks('magic_auth_success',$arr);
$arr = [
'xchan' => $hubloc,
'url' => \App::$query_string,
'session' => $_SESSION
];
/**
* @hooks magic_auth_success
* Called when a magic-auth was successful.
* * \e array \b xchan
* * \e string \b url
* * \e array \b session
*/
call_hooks('magic_auth_success', $arr);
\App::set_observer($hubloc);
require_once('include/security.php');
\App::set_groups(init_groups_visitor($_SESSION['visitor_id']));
if(! get_config('system','hide_owa_greeting'))
if(! get_config('system', 'hide_owa_greeting'))
info(sprintf( t('OpenWebAuth: %1$s welcomes %2$s'),\App::get_hostname(), $hubloc['xchan_name']));
logger('OpenWebAuth: auth success from ' . $hubloc['xchan_addr']);
}

File diff suppressed because it is too large Load diff