diff --git a/Zotlabs/Access/PermissionRoles.php b/Zotlabs/Access/PermissionRoles.php index 49d478c5c..b335bf825 100644 --- a/Zotlabs/Access/PermissionRoles.php +++ b/Zotlabs/Access/PermissionRoles.php @@ -1,12 +1,21 @@ [ - '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; } } \ No newline at end of file diff --git a/Zotlabs/Access/Permissions.php b/Zotlabs/Access/Permissions.php index 62c4af0ff..20ce21238 100644 --- a/Zotlabs/Access/Permissions.php +++ b/Zotlabs/Access/Permissions.php @@ -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 = []; diff --git a/Zotlabs/Extend/Hook.php b/Zotlabs/Extend/Hook.php index c6f9ea850..81260ead6 100644 --- a/Zotlabs/Extend/Hook.php +++ b/Zotlabs/Extend/Hook.php @@ -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); diff --git a/Zotlabs/Lib/ActivityStreams.php b/Zotlabs/Lib/ActivityStreams.php index 379e78a59..2e9bb0703 100644 --- a/Zotlabs/Lib/ActivityStreams.php +++ b/Zotlabs/Lib/ActivityStreams.php @@ -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; } diff --git a/Zotlabs/Lib/Chatroom.php b/Zotlabs/Lib/Chatroom.php index e1a9a10b3..e762620ae 100644 --- a/Zotlabs/Lib/Chatroom.php +++ b/Zotlabs/Lib/Chatroom.php @@ -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 ) diff --git a/Zotlabs/Lib/Config.php b/Zotlabs/Lib/Config.php index 6e042feba..f9f22ba3a 100644 --- a/Zotlabs/Lib/Config.php +++ b/Zotlabs/Lib/Config.php @@ -1,4 +1,4 @@ -PConfig is used for channel specific configurations and takes a + * channel_id 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 { } } - \ No newline at end of file diff --git a/Zotlabs/Lib/SConfig.php b/Zotlabs/Lib/SConfig.php index ca0d133b2..ab6f49025 100644 --- a/Zotlabs/Lib/SConfig.php +++ b/Zotlabs/Lib/SConfig.php @@ -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) { diff --git a/Zotlabs/Lib/XConfig.php b/Zotlabs/Lib/XConfig.php index bf78c360f..c5a108ac9 100644 --- a/Zotlabs/Lib/XConfig.php +++ b/Zotlabs/Lib/XConfig.php @@ -2,7 +2,26 @@ namespace Zotlabs\Lib; - +/** + * @brief Class for handling observer's config. + * + * XConfig is comparable to PConfig, except that it uses xchan + * (an observer hash) as an identifier. + * + * XConfig is used for observer specific configurations and takes a + * xchan 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), diff --git a/Zotlabs/Render/Comanche.php b/Zotlabs/Render/Comanche.php index 78ca870a7..cd06e11a8 100644 --- a/Zotlabs/Render/Comanche.php +++ b/Zotlabs/Render/Comanche.php @@ -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 = ''; 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; diff --git a/Zotlabs/Web/Router.php b/Zotlabs/Web/Router.php index 9486130cb..12ef315d4 100644 --- a/Zotlabs/Web/Router.php +++ b/Zotlabs/Web/Router.php @@ -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); } diff --git a/Zotlabs/Zot/Verify.php b/Zotlabs/Zot/Verify.php index 1d9e6de3f..7abe38d17 100644 --- a/Zotlabs/Zot/Verify.php +++ b/Zotlabs/Zot/Verify.php @@ -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(), diff --git a/boot.php b/boot.php index 9238b38f0..d3989acd3 100755 --- a/boot.php +++ b/boot.php @@ -1,7 +1,8 @@ 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 ); } diff --git a/include/acl_selectors.php b/include/acl_selectors.php index 09c24f82c..4e203074b 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -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()) diff --git a/include/attach.php b/include/attach.php index 78e133b03..bfe3d5d46 100644 --- a/include/attach.php +++ b/include/attach.php @@ -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; } diff --git a/include/channel.php b/include/channel.php index 399dff87e..6a6022aba 100644 --- a/include/channel.php +++ b/include/channel.php @@ -1,6 +1,7 @@ $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; -} \ No newline at end of file +} + diff --git a/include/datetime.php b/include/datetime.php index 85e87848b..0fcd957be 100644 --- a/include/datetime.php +++ b/include/datetime.php @@ -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)); diff --git a/include/event.php b/include/event.php index b56a5fb3e..282c1a9d7 100644 --- a/include/event.php +++ b/include/event.php @@ -1,15 +1,16 @@ ' . "\r\n"; @@ -29,27 +30,27 @@ function format_event_html($ev) { $o .= '
' . t('Starts:') . ' ' - . (($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))) . '
' . "\r\n"; if(! $ev['nofinish']) $o .= '
' . t('Finishes:') . ' ' - . (($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 ))) . '
' . "\r\n"; $o .= '
' . zidify_links(smilies(bbcode($ev['description']))) . '
' . "\r\n"; if(strlen($ev['location'])) - $o .= '
' . t('Location:') . ' ' + $o .= '
' . t('Location:') . ' ' . zidify_links(smilies(bbcode($ev['location']))) . '
' . "\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) { diff --git a/include/feedutils.php b/include/feedutils.php index 217da8188..1284c45a3 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -1,5 +1,8 @@ $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 .= '' . "\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,'' . "\r\n"; $o .= ' ' . $name . '' . "\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 .= "\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 .= ' ' . $nick . '' . "\r\n"; $o .= ' ' . $name . '' . "\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 .= "\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']; } - diff --git a/include/items.php b/include/items.php index 08e53553b..3934f6194 100755 --- a/include/items.php +++ b/include/items.php @@ -1,6 +1,7 @@ $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)); - } diff --git a/include/markdown.php b/include/markdown.php index 0464cf71a..865727b20 100644 --- a/include/markdown.php +++ b/include/markdown.php @@ -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(" ","\r",$s); $s = str_replace(" \n>","",$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; } diff --git a/include/network.php b/include/network.php index 2caf29ab5..3569874be 100644 --- a/include/network.php +++ b/include/network.php @@ -1,6 +1,7 @@ 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,' $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 isn’t 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 isn’t supported! + $AcceptTypes[$a] = $q; + } + arsort($AcceptTypes); - // Accept header is case insensitive, and whitespace isn’t 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 isn’t 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); + // let’s check our supported types: + foreach ($AcceptTypes as $mime => $q) { + if ($q && in_array($mime, $mimeTypes)) return $mime; + } - // let’s 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 []; - } \ No newline at end of file diff --git a/include/photos.php b/include/photos.php index 5de68f162..508121950 100644 --- a/include/photos.php +++ b/include/photos.php @@ -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(''), 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(''), 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; } +} diff --git a/include/plugin.php b/include/plugin.php index db20152ea..379d8e799 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -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; } diff --git a/include/zid.php b/include/zid.php index ce9f70385..084188770 100644 --- a/include/zid.php +++ b/include/zid.php @@ -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 \ 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 = ' $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']); - - } \ No newline at end of file diff --git a/include/zot.php b/include/zot.php index 5764bb99a..0aa50ab92 100644 --- a/include/zot.php +++ b/include/zot.php @@ -31,7 +31,6 @@ require_once('include/perm_upgrade.php'); * @param string $channel_nick a unique nickname of controlling entity * @returns string */ - function zot_new_uid($channel_nick) { $rawstr = z_root() . '/' . $channel_nick . '.' . mt_rand(); return(base64url_encode(hash('whirlpool', $rawstr, true), true)); @@ -49,7 +48,6 @@ function zot_new_uid($channel_nick) { * @param string $guid * @param string $guid_sig */ - function make_xchan_hash($guid, $guid_sig) { return base64url_encode(hash('whirlpool', $guid . $guid_sig, true)); } @@ -104,6 +102,8 @@ function zot_get_hublocs($hash) { * @param string $remote_key * optional public site key of target hub used to encrypt entire packet * NOTE: remote_key and encrypted packets are required for 'auth_check' packets, optional for all others + * @param string $methods + * optional comma separated list of encryption methods @ref zot_best_algorithm() * @param string $secret * random string, required for packets which require verification/callback * e.g. 'pickup', 'purge', 'notify', 'auth_check'. Packet types 'ping', 'force_refresh', and 'refresh' do not require verification @@ -159,29 +159,38 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot } /** - * @brief choose best encryption function from those available on both sites - * + * @brief Choose best encryption function from those available on both sites. + * * @param string $methods * comma separated list of encryption methods * @return string first match from our site method preferences crypto_methods() array * of a method which is common to both sites; or 'aes256cbc' if no matches are found. */ - function zot_best_algorithm($methods) { - $x = [ 'methods' => $methods, 'result' => '' ]; - call_hooks('zot_best_algorithm',$x); + $x = [ + 'methods' => $methods, + 'result' => '' + ]; + /** + * @hooks zot_best_algorithm + * Called when negotiating crypto algorithms with remote sites. + * * \e string \b methods - comma separated list of encryption methods + * * \e string \b result - the algorithm to return + */ + call_hooks('zot_best_algorithm', $x); + if($x['result']) return $x['result']; if($methods) { - $x = explode(',',$methods); + $x = explode(',', $methods); if($x) { $y = crypto_methods(); if($y) { foreach($y as $yv) { $yv = trim($yv); - if(in_array($yv,$x)) { + if(in_array($yv, $x)) { return($yv); } } @@ -193,7 +202,6 @@ function zot_best_algorithm($methods) { } - /** * @brief * @@ -210,7 +218,7 @@ function zot_zot($url, $data) { /** * @brief Refreshes after permission changed or friending, etc. * - * The top half of this function is similar to \Zotlabs\Zot\Finger::run() and could potentially be + * The top half of this function is similar to \\Zotlabs\\Zot\\Finger::run() and could potentially be * consolidated. * * zot_refresh is typically invoked when somebody has changed permissions of a channel and they are notified @@ -230,21 +238,22 @@ function zot_zot($url, $data) { * * @param array $them => xchan structure of sender * @param array $channel => local channel structure of target recipient, required for "friending" operations - * @param array $force default false + * @param array $force (optional) default false * - * @returns boolean true if successful, else false + * @return boolean + * * \b true if successful + * * otherwise \b false */ - function zot_refresh($them, $channel = null, $force = false) { if (array_key_exists('xchan_network', $them) && ($them['xchan_network'] !== 'zot')) { - logger('zot_refresh: not got zot. ' . $them['xchan_name']); + logger('not got zot. ' . $them['xchan_name']); return true; } - logger('zot_refresh: them: ' . print_r($them,true), LOGGER_DATA, LOG_DEBUG); + logger('them: ' . print_r($them,true), LOGGER_DATA, LOG_DEBUG); if ($channel) - logger('zot_refresh: channel: ' . print_r($channel,true), LOGGER_DATA, LOG_DEBUG); + logger('channel: ' . print_r($channel,true), LOGGER_DATA, LOG_DEBUG); $url = null; @@ -315,7 +324,6 @@ function zot_refresh($them, $channel = null, $force = false) { && array_key_exists('xchan_guid_sig',$them) && $them['xchan_guid_sig']) { $postvars['guid'] = $them['xchan_guid']; $postvars['guid_sig'] = $them['xchan_guid_sig']; - } $rhs = '/.well-known/zot-info'; @@ -330,7 +338,7 @@ function zot_refresh($them, $channel = null, $force = false) { $j = json_decode($result['body'],true); if (! (($j) && ($j['success']))) { - logger('zot_refresh: result not decodable'); + logger('Result not decodable'); return false; } @@ -484,7 +492,7 @@ function zot_refresh($them, $channel = null, $force = false) { } - /** If there is a default group for this channel, add this connection to it */ + // If there is a default group for this channel, add this connection to it $default_group = $channel['channel_default_group']; if($default_group) { @@ -528,10 +536,10 @@ function zot_refresh($them, $channel = null, $force = false) { * * \e string \b url_sig => URL signed with conversant's private key * @param boolean $multiple (optional) default false * - * @returns array|null null if site is blacklisted or not found, otherwise an - * array with an hubloc record + * @return array|null + * * null if site is blacklisted or not found + * * otherwise an array with an hubloc record */ - function zot_gethub($arr, $multiple = false) { if($arr['guid'] && $arr['guid_sig'] && $arr['url'] && $arr['url_sig']) { @@ -554,11 +562,11 @@ function zot_gethub($arr, $multiple = false) { dbesc($arr['url_sig']) ); if($r) { - logger('zot_gethub: found', LOGGER_DEBUG); + logger('Found', LOGGER_DEBUG); return (($multiple) ? $r : $r[0]); } } - logger('zot_gethub: not found: ' . print_r($arr,true), LOGGER_DEBUG); + logger('Not found: ' . print_r($arr,true), LOGGER_DEBUG); return false; } @@ -577,11 +585,10 @@ function zot_gethub($arr, $multiple = false) { * * \e string \b url => URL of the origination hub of this communication * * \e string \b url_sig => URL signed with conversant's private key * - * @returns array an associative array with + * @return array An associative array with * * \b success boolean true or false * * \b message (optional) error string only if success is false */ - function zot_register_hub($arr) { $result = [ 'success' => false ]; @@ -619,7 +626,7 @@ function zot_register_hub($arr) { $result['success'] = true; } else { - logger('zot_register_hub: failure to verify returned packet using ' . $method); + logger('Failure to verify returned packet using ' . $method); } } } @@ -642,13 +649,17 @@ function zot_register_hub($arr) { * If set [typically by update_directory_entry()] indicates a specific update table row and more particularly * contains a particular address (ud_addr) which needs to be updated in that table. * - * @return associative array + * @return array An associative array with: * * \e boolean \b success boolean true or false * * \e string \b message (optional) error string only if success is false */ +function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { -function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { - + /** + * @hooks import_xchan + * Called when processing the result of zot_finger() to store the result + * * \e array + */ call_hooks('import_xchan', $arr); $ret = array('success' => false); @@ -658,13 +669,13 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $what = ''; if(! (is_array($arr) && array_key_exists('success',$arr) && $arr['success'])) { - logger('import_xchan: invalid data packet: ' . print_r($arr,true)); + logger('Invalid data packet: ' . print_r($arr,true)); $ret['message'] = t('Invalid data packet'); return $ret; } if(! ($arr['guid'] && $arr['guid_sig'])) { - logger('import_xchan: no identity information provided. ' . print_r($arr,true)); + logger('No identity information provided. ' . print_r($arr,true)); return $ret; } @@ -678,7 +689,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { foreach($sig_methods as $method) { if(! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key'],$method)) { - logger('import_xchan: Unable to verify channel signature for ' . $arr['address'] . ' using ' . $method); + logger('Unable to verify channel signature for ' . $arr['address'] . ' using ' . $method); continue; } else { @@ -761,8 +772,8 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { dbesc($xchan_hash) ); - logger('import_xchan: update: existing: ' . print_r($r[0],true), LOGGER_DATA, LOG_DEBUG); - logger('import_xchan: update: new: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); + logger('Update: existing: ' . print_r($r[0],true), LOGGER_DATA, LOG_DEBUG); + logger('Update: new: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); $what .= 'xchan '; $changed = true; } @@ -777,7 +788,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $x = xchan_store_lowlevel( [ - 'xchan_hash' => $xchan_hash, + 'xchan_hash' => $xchan_hash, 'xchan_guid' => $arr['guid'], 'xchan_guid_sig' => $arr['guid_sig'], 'xchan_pubkey' => $arr['key'], @@ -928,7 +939,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { } } else { - logger('import_xchan: profile not available - hiding'); + logger('Profile not available - hiding'); // they may have made it private $r = q("delete from xprof where xprof_hash = '%s'", dbesc($xchan_hash) @@ -950,7 +961,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { if(($changed) || ($ud_flags == UPDATE_FLAGS_FORCED)) { $guid = random_string() . '@' . App::get_hostname(); update_modtime($xchan_hash,$guid,$address,$ud_flags); - logger('import_xchan: changed: ' . $what,LOGGER_DEBUG); + logger('Changed: ' . $what,LOGGER_DEBUG); } elseif(! $ud_flags) { // nothing changed but we still need to update the updates record @@ -966,7 +977,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $ret['hash'] = $xchan_hash; } - logger('import_xchan: result: ' . print_r($ret,true), LOGGER_DATA, LOG_DEBUG); + logger('Result: ' . print_r($ret,true), LOGGER_DATA, LOG_DEBUG); return $ret; } @@ -980,19 +991,18 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { * @param array $arr - output of z_post_url() * @param array $outq - The queue structure attached to this request */ - function zot_process_response($hub, $arr, $outq) { if(! $arr['success']) { - logger('zot_process_response: failed: ' . $hub); + logger('Failed: ' . $hub); return; } $x = json_decode($arr['body'], true); if(! $x) { - logger('zot_process_response: No json from ' . $hub); - logger('zot_process_response: headers: ' . print_r($arr['header'],true), LOGGER_DATA, LOG_DEBUG); + logger('No json from ' . $hub); + logger('Headers: ' . print_r($arr['header'], true), LOGGER_DATA, LOG_DEBUG); } if(is_array($x) && array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) { @@ -1000,7 +1010,7 @@ function zot_process_response($hub, $arr, $outq) { if(array_key_exists('iv',$x['delivery_report'])) { $j = crypto_unencapsulate($x['delivery_report'],get_config('system','prvkey')); if($j) { - $x['delivery_report'] = json_decode($j,true); + $x['delivery_report'] = json_decode($j,true); } if(! (is_array($x['delivery_report']) && count($x['delivery_report']))) { logger('encrypted delivery report could not be decrypted'); @@ -1060,7 +1070,6 @@ function zot_process_response($hub, $arr, $outq) { * decrypted and json decoded notify packet from remote site * @return array from zot_import() */ - function zot_fetch($arr) { logger('zot_fetch: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG); @@ -1073,7 +1082,7 @@ function zot_fetch($arr) { $ret_hubs = zot_gethub($arr['sender'],true); if(! $ret_hubs) { - logger('zot_fetch: no hub: ' . print_r($arr['sender'],true)); + logger('No hub: ' . print_r($arr['sender'],true)); return; } @@ -1105,7 +1114,6 @@ function zot_fetch($arr) { } return; - } /** @@ -1114,7 +1122,7 @@ function zot_fetch($arr) { * Process an incoming array of messages which were obtained via pickup, and * import, update, delete as directed. * - * The message types handled here are 'activity' (e.g. posts), 'mail' , + * The message types handled here are 'activity' (e.g. posts), 'mail', * 'profile', 'location' and 'channel_sync'. * * @param array $arr @@ -1126,18 +1134,17 @@ function zot_fetch($arr) { * currently processing. * * @returns array - * suitable for logging remotely, enumerating the processing results of each message/recipient combination - * * [0] => \e string $channel_hash - * * [1] => \e string $delivery_status - * * [2] => \e string $address + * Suitable for logging remotely, enumerating the processing results of each message/recipient combination + * * [0] => \e string $channel_hash + * * [1] => \e string $delivery_status + * * [2] => \e string $address */ - function zot_import($arr, $sender_url) { $data = json_decode($arr['body'], true); if(! $data) { - logger('zot_import: empty body'); + logger('Empty body'); return array(); } @@ -1173,7 +1180,7 @@ function zot_import($arr, $sender_url) { $i['notify'] = json_decode(crypto_unencapsulate($i['notify'],get_config('system','prvkey')),true); } - logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA, LOG_DEBUG); + logger('Notify: ' . print_r($i['notify'],true), LOGGER_DATA, LOG_DEBUG); if(! is_array($i['notify'])) { logger('decode error'); @@ -1183,7 +1190,7 @@ function zot_import($arr, $sender_url) { $hub = zot_gethub($i['notify']['sender']); if((! $hub) || ($hub['hubloc_url'] != $sender_url)) { - logger('zot_import: potential forgery: wrong site for sender: ' . $sender_url . ' != ' . print_r($i['notify'],true)); + logger('Potential forgery: wrong site for sender: ' . $sender_url . ' != ' . print_r($i['notify'],true)); continue; } @@ -1291,7 +1298,7 @@ function zot_import($arr, $sender_url) { } if(! $deliveries) { - logger('zot_import: no deliveries on this site'); + logger('No deliveries on this site'); continue; } @@ -1371,7 +1378,6 @@ function zot_import($arr, $sender_url) { * @param array $msg * @return NULL|array */ - function public_recips($msg) { require_once('include/channel.php'); @@ -1501,9 +1507,8 @@ function public_recips($msg) { } /** - * @brief + * @brief This is the second part of public_recips(). * - * This is the second part of public_recips(). * We'll find all the channels willing to accept public posts from us, then * match them against the sender privacy scope and see who in that list that * the sender is allowing. @@ -1583,7 +1588,6 @@ function allowed_public_recips($msg) { * @param boolean $request (optional) default false * @return array */ - function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) { $result = array(); @@ -1594,12 +1598,11 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ if(! $public) { if($sender['hash'] != $arr['owner_xchan'] && $sender['hash'] != $arr['author_xchan']) { - logger("process_delivery: sender {$sender['hash']} is not owner {$arr['owner_xchan']} or author {$arr['author_xchan']} - mid {$arr['mid']}"); + logger("Sender {$sender['hash']} is not owner {$arr['owner_xchan']} or author {$arr['author_xchan']} - mid {$arr['mid']}"); return; } } - foreach($deliveries as $d) { $local_public = $public; @@ -1828,7 +1831,6 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ $DR->update('update ignored'); $result[] = $DR->get(); - // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit), // and at the same time not relay any other relayable posts more than once, because to do so is very wasteful. if(! intval($r[0]['item_origin'])) @@ -1842,8 +1844,14 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ // if it's a sourced post, call the post_local hooks as if it were // posted locally so that crosspost connectors will be triggered. - if(check_item_source($arr['uid'], $arr)) + if(check_item_source($arr['uid'], $arr)) { + /** + * @hooks post_local + * Called when an item has been posted on this machine via mod/item.php (also via API). + * * \e array with an item + */ call_hooks('post_local', $arr); + } $item_id = 0; @@ -1855,8 +1863,21 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ $item_result = item_store($arr); if($item_result['success']) { $item_id = $item_result['item_id']; - $parr = array('item_id' => $item_id,'item' => $arr,'sender' => $sender,'channel' => $channel); - call_hooks('activity_received',$parr); + $parr = [ + 'item_id' => $item_id, + 'item' => $arr, + 'sender' => $sender, + 'channel' => $channel + ]; + /** + * @hooks activity_received + * Called when an activity (post, comment, like, etc.) has been received from a zot source. + * * \e int \b item_id + * * \e array \b item + * * \e array \b sender + * * \e array \b channel + */ + call_hooks('activity_received', $parr); // don't add a source route if it's a relay or later recipients will get a route mismatch if(! $relay) add_source_route($item_id,$sender['hash']); @@ -1875,7 +1896,7 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ } if($relay && $item_id) { - logger('process_delivery: invoking relay'); + logger('Invoking relay'); Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id))); $DR->addto_update('relayed'); $result[] = $DR->get(); @@ -1885,13 +1906,13 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ if(! $deliveries) $result[] = array('', 'no recipients', '', $arr['mid']); - logger('process_delivery: local results: ' . print_r($result, true), LOGGER_DEBUG); + logger('Local results: ' . print_r($result, true), LOGGER_DEBUG); return $result; } /** - * @brief + * @brief Remove community tag. * * @param array $sender an associative array with * * \e string \b hash a xchan_hash @@ -1901,7 +1922,6 @@ function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $ * * \e int \b mid * @param int $uid */ - function remove_community_tag($sender, $arr, $uid) { if(! (activity_match($arr['verb'], ACTIVITY_TAG) && ($arr['obj_type'] == ACTIVITY_OBJ_TAGTERM))) @@ -1910,7 +1930,7 @@ function remove_community_tag($sender, $arr, $uid) { logger('remove_community_tag: invoked'); if(! get_pconfig($uid,'system','blocktags')) { - logger('remove_community tag: permission denied.'); + logger('Permission denied.'); return; } @@ -1919,12 +1939,12 @@ function remove_community_tag($sender, $arr, $uid) { intval($uid) ); if(! $r) { - logger('remove_community_tag: no item'); + logger('No item'); return; } if(($sender['hash'] != $r[0]['owner_xchan']) && ($sender['hash'] != $r[0]['author_xchan'])) { - logger('remove_community_tag: sender not authorised.'); + logger('Sender not authorised.'); return; } @@ -1936,7 +1956,7 @@ function remove_community_tag($sender, $arr, $uid) { $i['object'] = json_decode($i['object'],true); if(! ($i['target'] && $i['object'])) { - logger('remove_community_tag: no target/object'); + logger('No target/object'); return; } @@ -1947,7 +1967,7 @@ function remove_community_tag($sender, $arr, $uid) { intval($uid) ); if(! $r) { - logger('remove_community_tag: no parent message'); + logger('No parent message'); return; } @@ -1963,16 +1983,16 @@ function remove_community_tag($sender, $arr, $uid) { } /** - * @brief Just calls item_store_update() and logs result. + * @brief Updates an imported item. * * @see item_store_update() * - * @param array $sender (unused) + * @param array $sender * @param array $item * @param array $orig * @param int $uid + * @param boolean $tag_delivery */ - function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) { // If this is a comment being updated, remove any privacy information @@ -1986,10 +2006,11 @@ function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) { unset($item['item_private']); } - // we need the tag_delivery check for downstream flowing posts as the stored post - // may have a different owner than the one being transmitted. + // we need the tag_delivery check for downstream flowing posts as the stored post + // may have a different owner than the one being transmitted. if(($sender['hash'] != $orig['owner_xchan'] && $sender['hash'] != $orig['author_xchan']) && (! $tag_delivery)) { + /// @fixme shouldn't this be logger? notice('sender is not owner or author'); return; } @@ -2024,10 +2045,9 @@ function update_imported_item($sender, $item, $orig, $uid, $tag_delivery) { * @param boolean $relay * @return boolean|int post_id */ - function delete_imported_item($sender, $item, $uid, $relay) { - logger('delete_imported_item invoked', LOGGER_DEBUG); + logger('invoked', LOGGER_DEBUG); $ownership_valid = false; $item_found = false; @@ -2186,7 +2206,6 @@ function process_mail_delivery($sender, $arr, $deliveries) { * * \e string \b hash a xchan_hash * @param array $arr */ - function process_rating_delivery($sender, $arr) { logger('process_rating_delivery: ' . print_r($arr,true)); @@ -2246,7 +2265,6 @@ function process_rating_delivery($sender, $arr) { * @param array $arr * @param array $deliveries (unused) */ - function process_profile_delivery($sender, $arr, $deliveries) { logger('process_profile_delivery', LOGGER_DEBUG); @@ -2258,7 +2276,16 @@ function process_profile_delivery($sender, $arr, $deliveries) { import_directory_profile($sender['hash'], $arr, $r[0]['xchan_addr'], UPDATE_FLAGS_UPDATED, 0); } -function process_location_delivery($sender,$arr,$deliveries) { + +/** + * @brief + * + * @param array $sender an associative array + * * \e string \b hash a xchan_hash + * @param array $arr + * @param array $deliveries (unused) deliveries is irrelevant + */ +function process_location_delivery($sender, $arr, $deliveries) { // deliveries is irrelevant logger('process_location_delivery', LOGGER_DEBUG); @@ -2271,7 +2298,7 @@ function process_location_delivery($sender,$arr,$deliveries) { if(array_key_exists('locations',$arr) && $arr['locations']) { $x = sync_locations($sender,$arr,true); - logger('process_location_delivery: results: ' . print_r($x,true), LOGGER_DEBUG); + logger('results: ' . print_r($x,true), LOGGER_DEBUG); if($x['changed']) { $guid = random_string() . '@' . App::get_hostname(); update_modtime($sender['hash'],$sender['guid'],$arr['locations'][0]['address'],UPDATE_FLAGS_UPDATED); @@ -2280,7 +2307,7 @@ function process_location_delivery($sender,$arr,$deliveries) { } /** - * @brief checks for a moved UNO channel and sets the channel_moved flag + * @brief Checks for a moved UNO channel and sets the channel_moved flag. * * Currently the effect of this flag is to turn the channel into 'read-only' mode. * New content will not be processed (there was still an issue with blocking the @@ -2294,11 +2321,11 @@ function process_location_delivery($sender,$arr,$deliveries) { * if a new location is reported and there is only one location record. * The rest of the hubloc syncronisation will be handled within * sync_locations + * + * @param string $sender_hash A channel hash + * @param array $locations */ - - - -function check_location_move($sender_hash,$locations) { +function check_location_move($sender_hash, $locations) { if(! $locations) return; @@ -2324,11 +2351,18 @@ function check_location_move($sender_hash,$locations) { // federation plugins may wish to notify connections // of the move on singleton networks - $arr = array('channel' => $r[0],'locations' => $locations); - call_hooks('location_move',$arr); - + $arr = [ + 'channel' => $r[0], + 'locations' => $locations + ]; + /** + * @hooks location_move + * Called when a new location has been provided to a UNO channel (indicating a move rather than a clone). + * * \e array \b channel + * * \e array \b locations + */ + call_hooks('location_move', $arr); } - } @@ -2340,7 +2374,6 @@ function check_location_move($sender_hash,$locations) { * @param boolean $absolute (optional) default false * @return array */ - function sync_locations($sender, $arr, $absolute = false) { $ret = array(); @@ -2350,7 +2383,6 @@ function sync_locations($sender, $arr, $absolute = false) { if($absolute) check_location_move($sender['hash'],$arr['locations']); - $xisting = q("select hubloc_id, hubloc_url, hubloc_sitekey from hubloc where hubloc_hash = '%s'", dbesc($sender['hash']) ); @@ -2372,7 +2404,7 @@ function sync_locations($sender, $arr, $absolute = false) { foreach($arr['locations'] as $location) { if(! rsa_verify($location['url'],base64url_decode($location['url_sig']),$sender['key'])) { - logger('sync_locations: Unable to verify site signature for ' . $location['url']); + logger('Unable to verify site signature for ' . $location['url']); $ret['message'] .= sprintf( t('Unable to verify site signature for %s'), $location['url']) . EOL; continue; } @@ -2385,7 +2417,7 @@ function sync_locations($sender, $arr, $absolute = false) { } if(! $location['sitekey']) { - logger('sync_locations: empty hubloc sitekey. ' . print_r($location,true)); + logger('Empty hubloc sitekey. ' . print_r($location,true)); continue; } @@ -2408,7 +2440,7 @@ function sync_locations($sender, $arr, $absolute = false) { dbesc($location['sitekey']) ); if($r) { - logger('sync_locations: hub exists: ' . $location['url'], LOGGER_DEBUG); + logger('Hub exists: ' . $location['url'], LOGGER_DEBUG); // update connection timestamp if this is the site we're talking to // This only happens when called from import_xchan @@ -2510,7 +2542,7 @@ function sync_locations($sender, $arr, $absolute = false) { dbesc($sender['hash']) ); } - logger('sync_locations: new hub: ' . $location['url']); + logger('New hub: ' . $location['url']); $r = hubloc_store_lowlevel( [ @@ -2548,7 +2580,7 @@ function sync_locations($sender, $arr, $absolute = false) { if($absolute && $xisting) { foreach($xisting as $x) { if(! array_key_exists('updated',$x)) { - logger('sync_locations: deleting unreferenced hub location ' . $x['hubloc_addr']); + logger('Deleting unreferenced hub location ' . $x['hubloc_addr']); $r = q("update hubloc set hubloc_deleted = 1, hubloc_updated = '%s' where hubloc_id = %d", dbesc(datetime_convert()), intval($x['hubloc_id']) @@ -2613,11 +2645,10 @@ function zot_encode_locations($channel) { * @param string $hash * @param array $profile * @param string $addr - * @param number $ud_flags - * @param number $suppress_update default 0 + * @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED + * @param number $suppress_update (optional) default 0 * @return boolean $updated if something changed */ - function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) { logger('import_directory_profile', LOGGER_DEBUG); @@ -2717,7 +2748,7 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA } } else { $update = true; - logger('import_directory_profile: new profile '); + logger('New profile'); q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_about, xprof_homepage, xprof_hometown, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", dbesc($arr['xprof_hash']), dbesc($arr['xprof_desc']), @@ -2737,7 +2768,18 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA ); } - $d = array('xprof' => $arr, 'profile' => $profile, 'update' => $update); + $d = [ + 'xprof' => $arr, + 'profile' => $profile, + 'update' => $update + ]; + /** + * @hooks import_directory_profile + * Called when processing delivery of a profile structure from an external source (usually for directory storage). + * * \e array \b xprof + * * \e array \b profile + * * \e boolean \b update + */ call_hooks('import_directory_profile', $d); if (($d['update']) && (! $suppress_update)) @@ -2749,10 +2791,9 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA /** * @brief * - * @param string $hash + * @param string $hash An xtag_hash * @param array $keywords */ - function import_directory_keywords($hash, $keywords) { $existing = array(); @@ -2797,7 +2838,6 @@ function import_directory_keywords($hash, $keywords) { * @param string $addr * @param int $flags (optional) default 0 */ - function update_modtime($hash, $guid, $addr, $flags = 0) { $dirmode = intval(get_config('system', 'directory_mode')); @@ -2830,13 +2870,12 @@ function update_modtime($hash, $guid, $addr, $flags = 0) { * @param string $pubkey * @return boolean true if updated or inserted */ - function import_site($arr, $pubkey) { if( (! is_array($arr)) || (! $arr['url']) || (! $arr['url_sig'])) return false; if(! rsa_verify($arr['url'], base64url_decode($arr['url_sig']), $pubkey)) { - logger('import_site: bad url_sig'); + logger('Bad url_sig'); return false; } @@ -2915,7 +2954,7 @@ function import_site($arr, $pubkey) { if(array_key_exists('zot',$arr)) { set_sconfig($arr['url'],'system','zot_version',$arr['zot']); - } + } if($exists) { if(($siterecord['site_flags'] != $site_flags) @@ -2934,7 +2973,6 @@ function import_site($arr, $pubkey) { // logger('import_site: input: ' . print_r($arr,true)); // logger('import_site: stored: ' . print_r($siterecord,true)); - $r = q("update site set site_dead = 0, site_location = '%s', site_flags = %d, site_access = %d, site_directory = '%s', site_register = %d, site_update = '%s', site_sellpage = '%s', site_realm = '%s', site_type = %d, site_project = '%s', site_version = '%s', site_crypto = '%s' where site_url = '%s'", dbesc($site_location), @@ -2952,7 +2990,7 @@ function import_site($arr, $pubkey) { dbesc($url) ); if(! $r) { - logger('import_site: update failed. ' . print_r($arr,true)); + logger('Update failed. ' . print_r($arr,true)); } } else { @@ -2966,7 +3004,7 @@ function import_site($arr, $pubkey) { else { $update = true; - $r = site_store_lowlevel( + $r = site_store_lowlevel( [ 'site_location' => $site_location, 'site_url' => $url, @@ -2985,7 +3023,7 @@ function import_site($arr, $pubkey) { ); if(! $r) { - logger('import_site: record create failed. ' . print_r($arr,true)); + logger('Record create failed. ' . print_r($arr,true)); } } @@ -2994,20 +3032,19 @@ function import_site($arr, $pubkey) { /** + * @brief Builds and sends a sync packet. + * * Send a zot packet to all hubs where this channel is duplicated, refreshing * such things as personal settings, channel permissions, address book updates, etc. * - * @param int $uid + * @param int $uid (optional) default 0 * @param array $packet (optional) default null * @param boolean $groups_changed (optional) default false */ - function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { - logger('build_sync_packet'); - $keychange = (($packet && array_key_exists('keychange',$packet)) ? true : false); if($keychange) { logger('keychange sync'); @@ -3122,6 +3159,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { ); if($r) $info['collections'] = $r; + $r = q("select groups.hash as collection, group_member.xchan as member from groups left join group_member on groups.id = group_member.gid where group_member.uid = %d", intval($uid) ); @@ -3132,7 +3170,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { $interval = ((get_config('system','delivery_interval') !== false) ? intval(get_config('system','delivery_interval')) : 2 ); - logger('build_sync_packet: packet: ' . print_r($info,true), LOGGER_DATA, LOG_DEBUG); + logger('Packet: ' . print_r($info,true), LOGGER_DATA, LOG_DEBUG); $total = count($synchubs); @@ -3173,7 +3211,6 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { * @param array $deliveries * @return array */ - function process_channel_sync_delivery($sender, $arr, $deliveries) { require_once('include/import.php'); @@ -3201,7 +3238,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $max_feeds = account_service_class_fetch($channel['channel_account_id'],'total_feeds'); if($channel['channel_hash'] != $sender['hash']) { - logger('process_channel_sync_delivery: possible forgery. Sender ' . $sender['hash'] . ' is not ' . $channel['channel_hash']); + logger('Possible forgery. Sender ' . $sender['hash'] . ' is not ' . $channel['channel_hash']); $result[] = array($d['hash'],'channel mismatch',$channel['channel_name'],''); continue; } @@ -3217,7 +3254,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $hash = make_xchan_hash($channel['channel_guid'],$sig); - $r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s', + $r = q("update channel set channel_prvkey = '%s', channel_pubkey = '%s', channel_guid_sig = '%s', channel_hash = '%s' where channel_id = %d", dbesc($arr['channel']['channel_prvkey']), dbesc($arr['channel']['channel_pubkey']), @@ -3360,7 +3397,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] - 0x8000; if($arr['channel']['channel_pageflags'] & 0x1000) $arr['channel']['channel_pageflags'] = $arr['channel']['channel_pageflags'] - 0x1000; - } $disallowed = [ @@ -3426,7 +3462,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $clean = array(); if($abook['abook_xchan'] && $abook['entry_deleted']) { - logger('process_channel_sync_delivery: removing abook entry for ' . $abook['abook_xchan']); + logger('Removing abook entry for ' . $abook['abook_xchan']); $r = q("select abook_id, abook_feed from abook where abook_xchan = '%s' and abook_channel = %d and abook_self = 0 limit 1", dbesc($abook['abook_xchan']), @@ -3451,7 +3487,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(! $h) { $xhash = import_author_xchan(encode_item_xchan($abook)); if(! $xhash) { - logger('process_channel_sync_delivery: import of ' . $abook['xchan_addr'] . ' failed.'); + logger('Import of ' . $abook['xchan_addr'] . ' failed.'); continue; } } @@ -3468,7 +3504,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(array_key_exists('abook_instance',$clean) && $clean['abook_instance'] && strpos($clean['abook_instance'],z_root()) === false) { $clean['abook_not_here'] = 1; - } + } $r = q("select * from abook where abook_xchan = '%s' and abook_channel = %d limit 1", @@ -3480,11 +3516,11 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(! $r) { if($max_friends !== false && $total_friends > $max_friends) { - logger('process_channel_sync_delivery: total_channels service class limit exceeded'); + logger('total_channels service class limit exceeded'); continue; } if($max_feeds !== false && intval($clean['abook_feed']) && $total_feeds > $max_feeds) { - logger('process_channel_sync_delivery: total_feeds service class limit exceeded'); + logger('total_feeds service class limit exceeded'); continue; } abook_store_lowlevel( @@ -3503,6 +3539,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { foreach($clean as $k => $v) { if($k == 'abook_dob') $v = dbescdate($v); + $r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v) . "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id'])); } @@ -3515,7 +3552,7 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { translate_abook_perms_inbound($channel,$abook); if($abconfig) { - // @fixme does not handle sync of del_abconfig + /// @fixme does not handle sync of del_abconfig foreach($abconfig as $abc) { set_abconfig($channel['channel_id'],$abc['xchan'],$abc['cat'],$abc['k'],$abc['v']); } @@ -3712,15 +3749,21 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { if(count($clean)) { foreach($clean as $k => $v) { $r = dbq("UPDATE profile set " . TQUOT . dbesc($k) . TQUOT . " = '" . dbesc($v) - . "' where profile_guid = '" . dbesc($profile['profile_guid']) + . "' where profile_guid = '" . dbesc($profile['profile_guid']) . "' and uid = " . intval($channel['channel_id'])); } } } } - $addon = array('channel' => $channel,'data' => $arr); - call_hooks('process_channel_sync_delivery',$addon); + $addon = ['channel' => $channel, 'data' => $arr]; + /** + * @hooks process_channel_sync_delivery + * Called when accepting delivery of a 'sync packet' containing structure and table updates from a channel clone. + * * \e array \b channel + * * \e array \b data + */ + call_hooks('process_channel_sync_delivery', $addon); // we should probably do this for all items, but usually we only send one. @@ -3732,7 +3775,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { $DR = new Zotlabs\Zot\DReport(z_root(),$d['hash'],$d['hash'],'sync packet','channel sync delivered'); $result[] = $DR->get(); - } return $result; @@ -3747,7 +3789,6 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { * * \e string \b xchan_url * @return string */ - function get_rpost_path($observer) { if(! $observer) return ''; @@ -3763,7 +3804,6 @@ function get_rpost_path($observer) { * @param array $x * @return boolean|string return false or a hash */ - function import_author_zot($x) { // Check that we have both a hubloc and xchan record - as occasionally storage calls will fail and @@ -3797,7 +3837,7 @@ function import_author_zot($x) { $site_dead = true; } - // We have valid and somewhat fresh information. + // We have valid and somewhat fresh information. if($r1 && $r2 && $r1[0]['hubloc_updated'] > datetime_convert('UTC','UTC','now - 1 week')) { logger('in cache', LOGGER_DEBUG); @@ -3806,16 +3846,16 @@ function import_author_zot($x) { logger('not in cache or cache stale - probing: ' . print_r($x,true), LOGGER_DEBUG,LOG_INFO); - // The primary hub may be dead. Try to find another one associated with this identity that is - // still alive. If we find one, use that url for the discovery/refresh probe. Otherwise, the dead site - // is all we have and there is no point probing it. Just return the hash indicating we have a - // cached entry and the identity is valid. It's just unreachable until they bring back their - // server from the grave or create another clone elsewhere. + // The primary hub may be dead. Try to find another one associated with this identity that is + // still alive. If we find one, use that url for the discovery/refresh probe. Otherwise, the dead site + // is all we have and there is no point probing it. Just return the hash indicating we have a + // cached entry and the identity is valid. It's just unreachable until they bring back their + // server from the grave or create another clone elsewhere. if($site_dead) { logger('dead site - ignoring', LOGGER_DEBUG,LOG_INFO); - $r = q("select hubloc_url from hubloc left join site on hubloc_url = site_url + $r = q("select hubloc_url from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and site_dead = 0", dbesc($hash) ); @@ -3826,8 +3866,7 @@ function import_author_zot($x) { else { return $hash; } - } - + } $them = array('hubloc_url' => $desturl, 'xchan_guid' => $x['guid'], 'xchan_guid_sig' => $x['guid_sig']); @@ -3854,7 +3893,6 @@ function import_author_zot($x) { * @param array $data * @return array */ - function zot_reply_message_request($data) { $ret = array('success' => false); @@ -3950,9 +3988,9 @@ function zot_rekey_request($sender,$data) { // newsig is newkey signed with oldkey // The original xchan will remain. In Zot/Receiver we will have imported the new xchan and hubloc to verify - // the packet authenticity. What we will do now is verify that the keychange operation was signed by the - // oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the - // old xchan_hash. + // the packet authenticity. What we will do now is verify that the keychange operation was signed by the + // oldkey, and if so change all the abook, abconfig, group, and permission elements which reference the + // old xchan_hash. if((! $data['old_key']) && (! $data['new_key']) && (! $data['new_sig'])) json_return_and_die($ret); @@ -4075,10 +4113,18 @@ function zotinfo($arr) { $id = $e['channel_id']; - $x = [ 'channel_id' => $id, 'protocols' => ['zot'] ]; - call_hooks('channel_protocols',$x); - $protocols = $x['protocols']; + $x = [ + 'channel_id' => $id, + 'protocols' => ['zot'] + ]; + /** + * @hooks channel_protocols + * * \e int \b channel_id + * * \e array \b protocols + */ + call_hooks('channel_protocols', $x); + $protocols = $x['protocols']; $sys_channel = (intval($e['channel_system']) ? true : false); $special_channel = (($e['channel_pageflags'] & PAGE_PREMIUM) ? true : false); @@ -4131,6 +4177,7 @@ function zotinfo($arr) { if($age = age($p[0]['dob'],$e['channel_timezone'],'')) $profile['age'] = $age; + $profile['gender'] = $p[0]['gender']; $profile['marital'] = $p[0]['marital']; $profile['sexual'] = $p[0]['sexual']; @@ -4190,7 +4237,6 @@ function zotinfo($arr) { $ret['deleted_locally'] = true; - // premium or other channel desiring some contact with potential followers before connecting. // This is a template - %s will be replaced with the follow_url we discover for the return channel. @@ -4234,10 +4280,14 @@ function zotinfo($arr) { check_zotinfo($e,$x,$ret); + /** + * @hooks zot_finger + * Called when a zot-info packet has been requested (this is our webfinger discovery mechanism). + * * \e array The final return array + */ + call_hooks('zot_finger', $ret); - call_hooks('zot_finger',$ret); return($ret); - } @@ -4328,11 +4378,17 @@ function zot_site_info($channel_key = '') { } return $ret['site']; - } -function check_zotinfo($channel,$locations,&$ret) { - +/** + * @brief + * + * @param array $channel + * @param array $locations + * @param[out] array $ret + * \e array \b locations result of zot_encode_locations() + */ +function check_zotinfo($channel, $locations, &$ret) { // logger('locations: ' . print_r($locations,true),LOGGER_DATA, LOG_DEBUG); @@ -4340,7 +4396,7 @@ function check_zotinfo($channel,$locations,&$ret) { // 1. Because magic-auth is reliant on it, ensure that the system channel has a valid hubloc // Force this to be the case if anything is found to be wrong with it. - // @FIXME ensure that the system channel exists in the first place and has an xchan + /// @FIXME ensure that the system channel exists in the first place and has an xchan if($channel['channel_system']) { // the sys channel must have a location (hubloc) @@ -4395,12 +4451,23 @@ function check_zotinfo($channel,$locations,&$ret) { } } +/** + * @brief + * + * @param array $dr + * @return boolean + */ function delivery_report_is_storable($dr) { - if(get_config('system','disable_dreport')) + if(get_config('system', 'disable_dreport')) return false; - call_hooks('dreport_is_storable',$dr); + /** + * @hooks dreport_is_storable + * Called before storing a dreport record to determine whether to store it. + * * \e array + */ + call_hooks('dreport_is_storable', $dr); // let plugins accept or reject - if neither, continue on if(array_key_exists('accept',$dr) && intval($dr['accept'])) @@ -4455,12 +4522,18 @@ function delivery_report_is_storable($dr) { return true; return false; - } - -function update_hub_connected($hub,$sitekey = '') { +/** + * @brief + * + * @param array $hub + * @param string $sitekey (optional, default empty) + * + * @return string hubloc_url + */ +function update_hub_connected($hub, $sitekey = '') { if($sitekey) { @@ -4489,7 +4562,7 @@ function update_hub_connected($hub,$sitekey = '') { // Update our DB to show when we last communicated successfully with this hub // This will allow us to prune dead hubs from using up resources - $t = datetime_convert('UTC','UTC','now - 15 minutes'); + $t = datetime_convert('UTC', 'UTC', 'now - 15 minutes'); $r = q("update hubloc set hubloc_connected = '%s' where hubloc_id = %d and hubloc_sitekey = '%s' and hubloc_connected < '%s' ", dbesc(datetime_convert()), @@ -4519,14 +4592,18 @@ function update_hub_connected($hub,$sitekey = '') { return $hub['hubloc_url']; } - +/** + * @brief Useful to get a health check on a remote site. + * + * This will let us know if any important communication details + * that we may have stored are no longer valid, regardless of xchan details. + * + * @return json_return_and_die() + */ function zot_reply_ping() { $ret = array('success'=> false); - // Useful to get a health check on a remote site. - // This will let us know if any important communication details - // that we may have stored are no longer valid, regardless of xchan details. logger('POST: got ping send pong now back: ' . z_root() , LOGGER_DEBUG ); $ret['success'] = true; @@ -4534,6 +4611,7 @@ function zot_reply_ping() { $ret['site']['url'] = z_root(); $ret['site']['url_sig'] = base64url_encode(rsa_sign(z_root(),get_config('system','prvkey'))); $ret['site']['sitekey'] = get_config('system','pubkey'); + json_return_and_die($ret); } @@ -4551,6 +4629,7 @@ function zot_reply_pickup($data) { if((! $data['secret']) || (! $data['secret_sig'])) { $ret['message'] = 'no verification signature'; logger('mod_zot: pickup: ' . $ret['message'], LOGGER_DEBUG); + json_return_and_die($ret); } @@ -4561,6 +4640,7 @@ function zot_reply_pickup($data) { if(! $r) { $ret['message'] = 'site not found'; logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); } @@ -4590,12 +4670,14 @@ function zot_reply_pickup($data) { if($forgery) { $ret['message'] = 'possible site forgery'; logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); } if($secret_fail) { $ret['message'] = 'secret validation failed'; logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); } @@ -4612,6 +4694,7 @@ function zot_reply_pickup($data) { if(! $r) { $ret['message'] = 'nothing to pick up'; logger('mod_zot: pickup: ' . $ret['message']); + json_return_and_die($ret); } @@ -4657,8 +4740,8 @@ function zot_reply_pickup($data) { $algorithm = zot_best_algorithm(($x) ? $x[0]['site_crypto'] : ''); $encrypted = crypto_encapsulate(json_encode($ret),$sitekey,$algorithm); - json_return_and_die($encrypted); + json_return_and_die($encrypted); /* pickup: end */ } @@ -4686,6 +4769,7 @@ function zot_reply_auth_check($data,$encrypted_packet) { if (! $encrypted_packet) { logger('mod_zot: auth_check packet was not encrypted.'); $ret['message'] .= 'no packet encryption' . EOL; + json_return_and_die($ret); } @@ -4694,11 +4778,12 @@ function zot_reply_auth_check($data,$encrypted_packet) { // garbage collect any old unused notifications - // This was and should be 10 minutes but my hosting provider has time lag between the DB and - // the web server. We should probably convert this to webserver time rather than DB time so - // that the different clocks won't affect it and allow us to keep the time short. - - Zotlabs\Zot\Verify::purge('auth','30 MINUTE'); + /** + * @TODO This was and should be 10 minutes but my hosting provider has time lag between the DB and + * the web server. We should probably convert this to webserver time rather than DB time so + * that the different clocks won't affect it and allow us to keep the time short. + */ + Zotlabs\Zot\Verify::purge('auth', '30 MINUTE'); $y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", dbesc($sender_hash) @@ -4712,6 +4797,7 @@ function zot_reply_auth_check($data,$encrypted_packet) { if ((! $y) || (! rsa_verify($data['secret'], base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) { logger('mod_zot: auth_check: sender not found or secret_sig invalid.'); $ret['message'] .= 'sender not found or sig invalid ' . print_r($y,true) . EOL; + json_return_and_die($ret); } @@ -4729,6 +4815,7 @@ function zot_reply_auth_check($data,$encrypted_packet) { if (! $c) { logger('mod_zot: auth_check: recipient channel not found.'); $ret['message'] .= 'recipient not found.' . EOL; + json_return_and_die($ret); } @@ -4737,11 +4824,11 @@ function zot_reply_auth_check($data,$encrypted_packet) { // This additionally checks for forged sites since we already stored the expected result in meta // and we've already verified that this is them via zot_gethub() and that their key signed our token - $z = Zotlabs\Zot\Verify::match('auth',$c[0]['channel_id'],$data['secret'],$data['sender']['url']); if (! $z) { logger('mod_zot: auth_check: verification key not found.'); $ret['message'] .= 'verification key not found' . EOL; + json_return_and_die($ret); } @@ -4769,11 +4856,19 @@ function zot_reply_auth_check($data,$encrypted_packet) { json_return_and_die($ret); } + json_return_and_die($ret); } - -function zot_reply_purge($sender,$recipients) { +/** + * @brief + * + * @param array $sender + * @param array $recipients + * + * return json_return_and_die() + */ +function zot_reply_purge($sender, $recipients) { $ret = array('success' => false); @@ -4811,17 +4906,23 @@ function zot_reply_purge($sender,$recipients) { json_return_and_die($ret); } - -function zot_reply_refresh($sender,$recipients) { +/** + * @brief Remote channel info (such as permissions or photo or something) + * has been updated. Grab a fresh copy and sync it. + * + * The difference between refresh and force_refresh is that force_refresh + * unconditionally creates a directory update record, even if no changes were + * detected upon processing. + * + * @param array $sender + * @param array $recipients + * + * @return json_return_and_die() + */ +function zot_reply_refresh($sender, $recipients) { $ret = array('success' => false); - // remote channel info (such as permissions or photo or something) - // has been updated. Grab a fresh copy and sync it. - // The difference between refresh and force_refresh is that - // force_refresh unconditionally creates a directory update record, - // even if no changes were detected upon processing. - if($recipients) { // This would be a permissions update, typically for one connection @@ -4842,7 +4943,7 @@ function zot_reply_refresh($sender,$recipients) { } } else { - // system wide refresh + // system wide refresh $x = zot_refresh(array( 'xchan_guid' => $sender['guid'], @@ -4853,7 +4954,6 @@ function zot_reply_refresh($sender,$recipients) { $ret['success'] = true; json_return_and_die($ret); - } @@ -4876,5 +4976,4 @@ function zot_reply_notify($data) { $ret['success'] = true; json_return_and_die($ret); - }