diff options
author | friendica <info@friendica.com> | 2015-03-29 16:05:24 -0700 |
---|---|---|
committer | friendica <info@friendica.com> | 2015-03-29 16:05:24 -0700 |
commit | b546f8d702157410a834000cc7a6aa621e78f427 (patch) | |
tree | 71dbbe2471783524af84f5fb21f4fa575e315247 /include | |
parent | 505e5e90b26fa398e08b6fcad266b7f0ac759bd2 (diff) | |
parent | 9ae9aedb15dfcb66f5bd9d866bdfb76309c81788 (diff) | |
download | volse-hubzilla-b546f8d702157410a834000cc7a6aa621e78f427.tar.gz volse-hubzilla-b546f8d702157410a834000cc7a6aa621e78f427.tar.bz2 volse-hubzilla-b546f8d702157410a834000cc7a6aa621e78f427.zip |
Merge https://github.com/friendica/red into pending_merge
Diffstat (limited to 'include')
-rwxr-xr-x | include/ITemplateEngine.php | 21 | ||||
-rw-r--r-- | include/account.php | 91 | ||||
-rw-r--r-- | include/attach.php | 116 | ||||
-rw-r--r-- | include/comanche.php | 36 | ||||
-rw-r--r-- | include/config.php | 29 | ||||
-rw-r--r-- | include/conversation.php | 8 | ||||
-rw-r--r-- | include/datetime.php | 452 | ||||
-rw-r--r-- | include/dir_fns.php | 212 | ||||
-rw-r--r-- | include/directory.php | 30 | ||||
-rw-r--r-- | include/enotify.php | 196 | ||||
-rw-r--r-- | include/event.php | 123 | ||||
-rw-r--r-- | include/expire.php | 59 | ||||
-rw-r--r-- | include/identity.php | 427 | ||||
-rwxr-xr-x | include/items.php | 862 | ||||
-rw-r--r-- | include/language.php | 93 | ||||
-rw-r--r-- | include/network.php | 99 | ||||
-rw-r--r-- | include/permissions.php | 28 | ||||
-rw-r--r-- | include/photos.php | 117 | ||||
-rwxr-xr-x | include/plugin.php | 44 | ||||
-rwxr-xr-x | include/template_processor.php | 540 | ||||
-rw-r--r-- | include/text.php | 331 | ||||
-rw-r--r-- | include/zot.php | 793 |
22 files changed, 2383 insertions, 2324 deletions
diff --git a/include/ITemplateEngine.php b/include/ITemplateEngine.php index 53c1845f4..7bd559a63 100755 --- a/include/ITemplateEngine.php +++ b/include/ITemplateEngine.php @@ -1,11 +1,10 @@ -<?php
-require_once 'boot.php';
-
-
-/**
- * Interface for template engines
- */
-interface ITemplateEngine {
- public function replace_macros($s,$v);
- public function get_markup_template($file, $root='');
-}
+<?php +require_once 'boot.php'; + +/** + * @brief Interface for template engines. + */ +interface ITemplateEngine { + public function replace_macros($s, $v); + public function get_markup_template($file, $root=''); +} diff --git a/include/account.php b/include/account.php index caac0b178..5926e05c1 100644 --- a/include/account.php +++ b/include/account.php @@ -1,4 +1,8 @@ -<?php /** @file */ +<?php +/** + * @file include/account.php + * @brief Somme account related functions. + */ require_once('include/config.php'); require_once('include/network.php'); @@ -43,15 +47,14 @@ function check_account_email($email) { function check_account_password($password) { $result = array('error' => false, 'message' => ''); - // The only validation we perform by default is pure Javascript to + // The only validation we perform by default is pure Javascript to // check minimum length and that both entered passwords match. - // Use hooked functions to perform complexity requirement checks. + // Use hooked functions to perform complexity requirement checks. $arr = array('password' => $password, 'result' => $result); call_hooks('check_account_password', $arr); return $arr['result']; - } function check_account_invite($invite_code) { @@ -75,7 +78,6 @@ function check_account_invite($invite_code) { call_hooks('check_account_invite', $arr); return $arr['result']; - } function check_account_admin($arr) { @@ -109,7 +111,7 @@ function create_account($arr) { $flags = ((x($arr,'account_flags')) ? intval($arr['account_flags']) : ACCOUNT_OK); $roles = ((x($arr,'account_roles')) ? intval($arr['account_roles']) : 0 ); $expires = ((x($arr,'expires')) ? intval($arr['expires']) : NULL_DATE); - + $default_service_class = get_config('system','default_service_class'); if($default_service_class === false) @@ -132,16 +134,16 @@ function create_account($arr) { // allow the admin_email account to be admin, but only if it's the first account. $c = account_total(); - if(($c === 0) && (check_account_admin($arr))) + if (($c === 0) && (check_account_admin($arr))) $roles |= ACCOUNT_ROLE_ADMIN; - // Ensure that there is a host keypair. + // Ensure that there is a host keypair. - if((! get_config('system','pubkey')) && (! get_config('system','prvkey'))) { - $hostkey = new_keypair(4096); - set_config('system','pubkey',$hostkey['pubkey']); - set_config('system','prvkey',$hostkey['prvkey']); - } + if ((! get_config('system', 'pubkey')) && (! get_config('system', 'prvkey'))) { + $hostkey = new_keypair(4096); + set_config('system', 'pubkey', $hostkey['pubkey']); + set_config('system', 'prvkey', $hostkey['prvkey']); + } $invite_result = check_account_invite($invite_code); if($invite_result['error']) { @@ -180,7 +182,6 @@ function create_account($arr) { dbesc($roles), dbesc($expires), dbesc($default_service_class) - ); if(! $r) { logger('create_account: DB INSERT failed.'); @@ -195,7 +196,7 @@ function create_account($arr) { if($r && count($r)) { $result['account'] = $r[0]; } - else { + else { logger('create_account: could not retrieve newly created account'); } @@ -215,8 +216,8 @@ function create_account($arr) { $result['success'] = true; $result['email'] = $email; $result['password'] = $password; - return $result; + return $result; } @@ -255,7 +256,6 @@ function verify_email_address($arr) { logger('send_reg_approval_email: failed to ' . $admin['email'] . 'account_id: ' . $arr['account']['account_id']); return $res; - } @@ -292,7 +292,6 @@ function send_reg_approval_email($arr) { $details = (($ip) ? $ip . ' [' . gethostbyaddr($ip) . ']' : '[unknown or stealth IP]'); - $delivered = 0; foreach($admins as $admin) { @@ -346,11 +345,14 @@ function send_verification_email($email,$password) { return($res ? true : false); } - +/** + * @brief Allows a user registration. + * + * @param string $hash + * @return array|boolean + */ function user_allow($hash) { - $a = get_app(); - $ret = array('success' => false); $register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", @@ -363,7 +365,7 @@ function user_allow($hash) { $account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1", intval($register[0]['uid']) ); - + if(! $account) return $ret; @@ -381,7 +383,7 @@ function user_allow($hash) { intval(ACCOUNT_PENDING), intval($register[0]['uid']) ); - + push_lang($register[0]['language']); $email_tpl = get_intltext_template("register_open_eml.tpl"); @@ -402,18 +404,23 @@ function user_allow($hash) { pop_lang(); - if($res) { + if ($res) { info( t('Account approved.') . EOL ); return true; - } - + } } -// This does not have to go through user_remove() and save the nickname -// permanently against re-registration, as the person was not yet -// allowed to have friends on this system - +/** + * @brief Denies a user registration. + * + * This does not have to go through user_remove() and save the nickname + * permanently against re-registration, as the person was not yet + * allowed to have friends on this system + * + * @param string $hash + * @return boolean + */ function user_deny($hash) { $register = q("SELECT * FROM register WHERE hash = '%s' LIMIT 1", @@ -426,7 +433,7 @@ function user_deny($hash) { $account = q("SELECT account_id, account_email FROM account WHERE account_id = %d LIMIT 1", intval($register[0]['uid']) ); - + if(! $account) return false; @@ -438,15 +445,14 @@ function user_deny($hash) { dbesc($register[0]['id']) ); notice( sprintf(t('Registration revoked for %s'), $account[0]['account_email']) . EOL); + return true; - + } function user_approve($hash) { - $a = get_app(); - $ret = array('success' => false); $register = q("SELECT * FROM `register` WHERE `hash` = '%s' and password = 'verify' LIMIT 1", @@ -459,7 +465,7 @@ function user_approve($hash) { $account = q("SELECT * FROM account WHERE account_id = %d LIMIT 1", intval($register[0]['uid']) ); - + if(! $account) return $ret; @@ -482,21 +488,16 @@ function user_approve($hash) { intval(ACCOUNT_UNVERIFIED), intval($register[0]['uid']) ); - + info( t('Account verified. Please login.') . EOL ); return true; - } - - - - /** - * @function downgrade_accounts() - * Checks for accounts that have past their expiration date. + * @brief Checks for accounts that have past their expiration date. + * * If the account has a service class which is not the site default, * the service class is reset to the site default and expiration reset to never. * If the account has no service class it is expired and subsequently disabled. @@ -506,8 +507,6 @@ function user_approve($hash) { * not the job of this function, but this can be implemented by plugin if desired. * Default behaviour is to stop allowing additional resources to be consumed. */ - - function downgrade_accounts() { $r = q("select * from account where not ( account_flags & %d )>0 @@ -604,7 +603,7 @@ function service_class_allows($uid, $property, $usage = false) { * * @param int $aid The account_id to check * @param string $property The service class property to check for - * @param int|boolean $usage, (optional) The value to check against + * @param int|boolean $usage (optional) The value to check against * @return boolean */ function account_service_class_allows($aid, $property, $usage = false) { diff --git a/include/attach.php b/include/attach.php index f9206851e..415859b39 100644 --- a/include/attach.php +++ b/include/attach.php @@ -1,10 +1,10 @@ <?php - -/** @file +/** + * @file include/attach.php * * @brief File/attach API with the potential for revision control. * - * TODO: a filesystem storage abstraction which maintains security (and 'data' contains a system filename + * @TODO: a filesystem storage abstraction which maintains security (and 'data' contains a system filename * which is inaccessible from the web). This could get around PHP storage limits and store videos and larger * items, using fread or OS methods or native code to read/write or chunk it through. * Also an 'append' option to the storage function might be a useful addition. @@ -15,10 +15,10 @@ require_once('include/security.php'); /** * @brief Guess the mimetype from file ending. - * + * * This function takes a file name and guess the mimetype from the * filename extension. - * + * * @param $filename a string filename * @return string The mimetype according to a file ending. */ @@ -117,23 +117,22 @@ function z_mime_content_type($filename) { /** * @brief Count files/attachments. - * - * - * @param $channel_id - * @param $observer - * @param $hash (optional) - * @param $filename (optional) - * @param $filetype (optional) - * @return array - * $ret['success'] boolean - * $ret['results'] amount of found results, or false - * $ret['message'] string with error messages if any + * + * @param int $channel_id + * @param string $observer + * @param string $hash (optional) + * @param string $filename (optional) + * @param string $filetype (optional) + * @return assoziative array with: + * * \e boolean \b success + * * \e int|boolean \b results amount of found results, or false + * * \e string \b message with error messages if any */ function attach_count_files($channel_id, $observer, $hash = '', $filename = '', $filetype = '') { $ret = array('success' => false); - if(! perm_is_allowed($channel_id,$observer, 'read_storage')) { + if(! perm_is_allowed($channel_id, $observer, 'read_storage')) { $ret['message'] = t('Permission denied.'); return $ret; } @@ -219,8 +218,9 @@ function attach_list_files($channel_id, $observer, $hash = '', $filename = '', $ * * This could exhaust memory so most useful only when immediately sending the data. * - * @param $hash - * @param $rev + * @param string $hash + * @param int $rev Revision + * @return array */ function attach_by_hash($hash, $rev = 0) { @@ -234,7 +234,6 @@ function attach_by_hash($hash, $rev = 0) { elseif($rev) $sql_extra = " and revision = " . intval($rev) . " "; - $r = q("SELECT uid FROM attach WHERE hash = '%s' $sql_extra LIMIT 1", dbesc($hash) ); @@ -270,9 +269,9 @@ function attach_by_hash($hash, $rev = 0) { /** * @brief Find an attachment by hash and revision. - * + * * Returns the entire attach structure excluding data. - * + * * @see attach_by_hash() * @param $hash * @param $rev revision default 0 @@ -561,7 +560,7 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { } else $paths = array($pathname); - + $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where id = %d and folder = '%s' and filename = '%s' and (flags & %d )>0 " . permissions_sql($channel_id), intval($channel_id), dbesc($parent_hash), @@ -579,24 +578,22 @@ function z_readdir($channel_id, $observer_hash, $pathname, $parent_hash = '') { } /** - * @function attach_mkdir($channel,$observer_hash,$arr); - * * @brief Create directory. * * @param array $channel channel array of owner * @param string $observer_hash hash of current observer * @param array $arr parameter array to fulfil request - * Required: - * $arr['filename'] - * $arr['folder'] // hash of parent directory, empty string for root directory - * Optional: - * $arr['hash'] // precumputed hash for this node - * $arr['allow_cid'] - * $arr['allow_gid'] - * $arr['deny_cid'] - * $arr['deny_gid'] + * - Required: + * * \e string \b filename + * * \e string \b folder hash of parent directory, empty string for root directory + * - Optional: + * * \e string \b hash precumputed hash for this node + * * \e tring \b allow_cid + * * \e string \b allow_gid + * * \e string \b deny_cid + * * \e string \b deny_gid + * @return array */ - function attach_mkdir($channel, $observer_hash, $arr = null) { $ret = array('success' => false); @@ -720,13 +717,13 @@ function attach_mkdir($channel, $observer_hash, $arr = null) { /** * @brief Changes permissions of a file. * - * @param $channel_id - * @param $resource - * @param $allow_cid - * @param $allow_gid - * @param $deny_cid - * @param $deny_gid - * @param $recurse + * @param int $channel_id + * @param array $resource + * @param string $allow_cid + * @param string $allow_gid + * @param string $deny_cid + * @param string $deny_gid + * @param boolean $recurse (optional) default false */ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse = false) { @@ -836,7 +833,6 @@ function attach_delete($channel_id, $resource) { ); file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $no_activity=false); - } /** @@ -844,8 +840,8 @@ function attach_delete($channel_id, $resource) { * * @warning This function cannot be used with mod/dav as it always returns a * path valid under mod/cloud. - * - * @param array assoziative array with: + * + * @param array $arr assoziative array with: * * \e int \b uid the channel's uid * * \e string \b folder * * \e string \b filename @@ -973,20 +969,21 @@ function pipe_streams($in, $out) { $size = 0; while (!feof($in)) $size += fwrite($out, fread($in, 8192)); + return $size; } /** - * @brief Activity for files + * @brief Activity for files. * - * @param $channel_id - * @param $object - * @param $allow_cid - * @param $allow_gid - * @param $deny_cid - * @param $deny_gid - * @param $verb - * @param $no_activity + * @param int $channel_id + * @param array $object + * @param string $allow_cid + * @param string $allow_gid + * @param string $deny_cid + * @param string $deny_gid + * @param string $verb + * @param boolean $no_activity */ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $verb, $no_activity) { @@ -1028,7 +1025,6 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, //filter out receivers which do not have permission to view filestorage $arr_allow_cid = check_list_permissions($channel_id, $arr_allow_cid, 'view_storage'); - } $mid = item_message_id(); @@ -1109,7 +1105,6 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $update = false; //notice( t('File activity updated') . EOL); - } if($no_activity) { @@ -1152,15 +1147,14 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, //(($verb === 'post') ? notice( t('File activity posted') . EOL) : notice( t('File activity dropped') . EOL)); return; - } /** * @brief Create file activity object * - * @param $channel_id - * @param $hash - * @param $cloudpath + * @param int $channel_id + * @param string $hash + * @param string $cloudpath */ function get_file_activity_object($channel_id, $hash, $cloudpath) { @@ -1199,8 +1193,8 @@ function get_file_activity_object($channel_id, $hash, $cloudpath) { 'deny_cid' => $x[0]['deny_cid'], 'deny_gid' => $x[0]['deny_gid'] ); - return $object; + return $object; } /** diff --git a/include/comanche.php b/include/comanche.php index 71ffe99b8..62bfd0ddc 100644 --- a/include/comanche.php +++ b/include/comanche.php @@ -101,7 +101,7 @@ function comanche_parser(&$a, $s, $pass = 0) { } -function comanche_menu($name,$class = '') { +function comanche_menu($name, $class = '') { $channel_id = comanche_get_channel_id(); if($channel_id) { $m = menu_fetch($name,$channel_id, get_observer_hash()); @@ -111,20 +111,23 @@ function comanche_menu($name,$class = '') { function comanche_replace_region($match) { $a = get_app(); - if(array_key_exists($match[1], $a->page)) { + if (array_key_exists($match[1], $a->page)) { return $a->page[$match[1]]; } } /** - * @function comanche_get_channel_id() - * Returns the channel_id of the profile owner of the page, or the local_channel if there is no profile owner. - * Otherwise returns 0 - */ - + * @brief Returns the channel_id of the profile owner of the page. + * + * 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 + */ function comanche_get_channel_id() { $channel_id = ((is_array(get_app()->profile)) ? get_app()->profile['profile_uid'] : 0); - if((! $channel_id) && (local_channel())) + + if ((! $channel_id) && (local_channel())) $channel_id = local_channel(); return $channel_id; @@ -173,23 +176,26 @@ function comanche_webpage(&$a,$s) { } -// Widgets will have to get any operational arguments from the session, -// the global app environment, or config storage until we implement argument passing - - +/** + * Widgets will have to get any operational arguments from the session, the + * global app environment, or config storage until we implement argument passing + * + * @param string $name + * @param string $text + */ function comanche_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) { + if ($cnt) { + foreach ($matches as $mtch) { $vars[$mtch[1]] = $mtch[2]; } } $func = 'widget_' . trim($name); - if(function_exists($func)) + if (function_exists($func)) return $func($vars); } diff --git a/include/config.php b/include/config.php index b459e2c7d..c94d25eb8 100644 --- a/include/config.php +++ b/include/config.php @@ -3,8 +3,7 @@ * @file include/config.php * @brief Arbitrary configuration storage. * - * Note: - * Please do not store booleans - convert to 0/1 integer values + * @note Please do not store booleans - convert to 0/1 integer values. * The get_?config() functions return boolean false for keys that are unset, * and this could lead to subtle bugs. * @@ -18,19 +17,20 @@ * - <b>pconfig</b> is used for channel specific configurations and takes a * <i>channel_id</i> as identifier. It stores for example which features are * enabled per channel. The storage is of size MEDIUMTEXT. - * @code $var = get_pconfig(local_channel(), 'category', 'key');@endcode + * @code{.php} $var = get_pconfig(local_channel(), 'category', 'key');@endcode * - <b>xconfig</b> is the same as pconfig, except that it uses <i>xchan</i> as * an identifier. This is for example for people who do not have a local account. * The storage is of size MEDIUMTEXT. - * @code $observer = $a->get_observer_hash(); + * @code{.php} + * $observer = $a->get_observer_hash(); * if ($observer) { * $var = get_xconfig($observer, 'category', 'key'); * }@endcode * * - get_config() and set_config() can also be done through the command line tool - * @ref util/config + * @ref util/config.md "util/config" * - get_pconfig() and set_pconfig() can also be done through the command line tool - * @ref util/pconfig and takes a channel_id as first argument. + * @ref util/pconfig.md "util/pconfig" and takes a channel_id as first argument. * */ @@ -123,7 +123,7 @@ function get_config_from_storage($family, $key) { * * Stores a config value ($value) in the category ($family) under the key ($key). * - * Please do not store booleans - convert to 0/1 integer values! + * @note Please do not store booleans - convert to 0/1 integer values! * * @param string $family * The category of the configuration value @@ -272,14 +272,16 @@ function get_pconfig($uid, $family, $key, $instore = false) { * Stores a config value ($value) in the category ($family) under the key ($key) * for the channel_id $uid. * - * Please do not store booleans - convert to 0/1 integer values! + * @note Please do not store booleans - convert to 0/1 integer values! * * @param string $uid * The channel_id * @param string $family * The category of the configuration value * @param string $key - * The configuration key to query + * The configuration key to set + * @param string $value + * The value to store * @return mixed Stored $value or false */ function set_pconfig($uid, $family, $key, $value) { @@ -315,6 +317,7 @@ function set_pconfig($uid, $family, $key, $value) { ); if($ret) return $value; + return $ret; } @@ -339,6 +342,7 @@ function set_pconfig($uid, $family, $key, $value) { if($ret) return $value; + return $ret; } @@ -360,13 +364,14 @@ function del_pconfig($uid, $family, $key) { global $a; $ret = false; - if(x($a->config[$uid][$family], $key)) + if (x($a->config[$uid][$family], $key)) unset($a->config[$uid][$family][$key]); $ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'", intval($uid), dbesc($family), dbesc($key) ); + return $ret; } @@ -448,7 +453,7 @@ function get_xconfig($xchan, $family, $key) { * Stores a config value ($value) in the category ($family) under the key ($key) * for the observer's $xchan hash. * - * Please do not store booleans - convert to 0/1 integer values! + * @note Please do not store booleans - convert to 0/1 integer values! * * @param string $xchan * The observer's hash @@ -456,6 +461,8 @@ function get_xconfig($xchan, $family, $key) { * The category of the configuration value * @param string $key * The configuration key to set + * @param string $value + * The value to store * @return mixed Stored $value or false */ function set_xconfig($xchan, $family, $key, $value) { diff --git a/include/conversation.php b/include/conversation.php index 4018ced28..042d01b3e 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1044,7 +1044,6 @@ function builtin_activity_puller($item, &$conv_responses) { return; } } - } @@ -1053,7 +1052,7 @@ function builtin_activity_puller($item, &$conv_responses) { * * @param int $cnt number of people who like/dislike the item * @param array $arr array of pre-linked names of likers/dislikers - * @param string $typ eone of 'like, 'dislike' + * @param string $type one of 'like, 'dislike' * @param int $id item id * @return string formatted text */ @@ -1146,7 +1145,6 @@ function status_editor($a, $x, $popup = false) { '$expireswhen' => t('Expires YYYY-MM-DD HH:MM') )); - $tpl = get_markup_template('jot.tpl'); $jotplugins = ''; @@ -1461,8 +1459,8 @@ function network_tabs() { if ($no_active=='active' && x($_GET,'order')) { switch($_GET['order']){ - case 'post': $postord_active = 'active'; $no_active=''; break; - case 'comment' : $all_active = 'active'; $no_active=''; break; + case 'post': $postord_active = 'active'; $no_active=''; break; + case 'comment' : $all_active = 'active'; $no_active=''; break; } } diff --git a/include/datetime.php b/include/datetime.php index 5cab5889d..b0167edb2 100644 --- a/include/datetime.php +++ b/include/datetime.php @@ -1,54 +1,71 @@ -<?php /** @file */ - -// two-level sort for timezones. +<?php +/** + * @file include/datetime.php + * @brief Some functions for date and time related tasks. + */ +/** + * @brief Two-level sort for timezones. + * + * @param string $a + * @param string $b + * @return number + */ function timezone_cmp($a, $b) { if(strstr($a,'/') && strstr($b,'/')) { if ( t($a) == t($b)) return 0; return ( t($a) < t($b)) ? -1 : 1; } - if(strstr($a,'/')) return -1; - if(strstr($b,'/')) return 1; + if (strstr($a,'/')) return -1; + if (strstr($b,'/')) return 1; if ( t($a) == t($b)) return 0; + return ( t($a) < t($b)) ? -1 : 1; } -// Return timezones grouped (primarily) by continent +/** + * @brief Return timezones grouped (primarily) by continent. + * + * @return array + */ function get_timezones( ){ $timezone_identifiers = DateTimeZone::listIdentifiers(); usort($timezone_identifiers, 'timezone_cmp'); $continent = ''; $continents = array(); - foreach($timezone_identifiers as $value) { + foreach ($timezone_identifiers as $value) { $ex = explode("/", $value); - if(count($ex) > 1) { + if (count($ex) > 1) { $continent = t($ex[0]); - if(count($ex) > 2) - $city = substr($value,strpos($value,'/')+1); + if (count($ex) > 2) + $city = substr($value, strpos($value, '/')+1); else $city = $ex[1]; - } - else { + } else { $city = $ex[0]; $continent = t('Miscellaneous'); } $city = str_replace('_', ' ', t($city)); - if(!x($continents,$ex[0])) $continents[$ex[0]] = array(); + if (!x($continents, $ex[0])) $continents[$ex[0]] = array(); $continents[$continent][$value] = $city; } + return $continents; } -// General purpose date parse/convert function. -// $from = source timezone -// $to = dest timezone -// $s = some parseable date/time string -// $fmt = output format - - +/** + * @brief General purpose date parse/convert function. + * + * @param string $from source timezone + * @param string $to dest timezone + * @param string $s some parseable date/time string + * @param string $fmt output format recognised from php's DateTime class + * http://www.php.net/manual/en/datetime.format.php + * @return string + */ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d H:i:s") { // Defaults to UTC if nothing is set, but throws an exception if set to empty string. @@ -68,44 +85,46 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d if(substr($s,0,10) == '0000-00-00') { $d = new DateTime($s . ' + 32 days', new DateTimeZone('UTC')); - return str_replace('1','0',$d->format($fmt)); + return str_replace('1', '0', $d->format($fmt)); } try { $from_obj = new DateTimeZone($from); - } - catch(Exception $e) { + } catch(Exception $e) { $from_obj = new DateTimeZone('UTC'); } try { $d = new DateTime($s, $from_obj); - } - catch(Exception $e) { + } catch(Exception $e) { logger('datetime_convert: exception: ' . $e->getMessage()); $d = new DateTime('now', $from_obj); } try { $to_obj = new DateTimeZone($to); - } - catch(Exception $e) { + } catch(Exception $e) { $to_obj = new DateTimeZone('UTC'); } $d->setTimeZone($to_obj); + return($d->format($fmt)); } -// wrapper for date selector, tailored for use in birthday fields - +/** + * @brief Wrapper for date selector, tailored for use in birthday fields. + * + * @param string $dob Date of Birth + * @return string + */ function dob($dob) { - list($year,$month,$day) = sscanf($dob,'%4d-%2d-%2d'); - $f = get_config('system','birthday_input_format'); - if(! $f) + list($year, $month, $day) = sscanf($dob, '%4d-%2d-%2d'); + $f = get_config('system', 'birthday_input_format'); + if (! $f) $f = 'ymd'; - if($dob === '0000-00-00') + if ($dob === '0000-00-00') $value = ''; else $value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d')); @@ -120,7 +139,6 @@ function dob($dob) { return $o; } - /** * returns a date selector * @param $format @@ -135,7 +153,7 @@ function dob($dob) { * 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, '', ''); } /** @@ -154,7 +172,8 @@ function timesel($format, $h, $m, $id='timepicker') { } /** - * returns a datetime selector + * @brief Returns a datetime selector. + * * @param $format * format string, e.g. 'ymd' or 'mdy'. Not currently supported * @param $min @@ -163,23 +182,25 @@ function timesel($format, $h, $m, $id='timepicker') { * unix timestap of maximum date * @param $default * unix timestamp of default date - * @param $id + * @param string $id * id and name of datetimepicker (defaults to "datetimepicker") - * @param $pickdate + * @param boolean $pickdate * true to show date picker (default) - * @param $picktime + * @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) + * @param boolean $required default false + * @return string Parsed HTML output. + * + * @todo Once browser support is better this could probably be replaced with + * native HTML5 date picker. */ -function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '',$required = false) { +function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false) { - - // Once browser support is better this could probably be replaced with native HTML5 date picker $o = ''; - $dateformat = ''; if($pickdate) $dateformat .= 'Y-m-d'; @@ -188,7 +209,7 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic $minjs = $min ? ",minDate: new Date({$min->getTimestamp()}*1000), yearStart: " . $min->format('Y') : ''; $maxjs = $max ? ",maxDate: new Date({$max->getTimestamp()}*1000), yearEnd: " . $max->format('Y') : ''; - + $input_text = $default ? 'value="' . date($dateformat, $default->getTimestamp()) . '"' : ''; $defaultdatejs = $default ? ",defaultDate: new Date({$default->getTimestamp()}*1000)" : ''; @@ -214,31 +235,39 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic $o .= (($required) ? '<span class="required" title="' . t('Required') . '" >*</span>' : ''); $o .= '</div>'; $o .= "<script type='text/javascript'>\$(function () {var picker = \$('#$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs}); $extra_js})</script>"; + return $o; } -// implements "3 seconds ago" etc. -// based on $posted_date, (UTC). -// Results relative to current timezone -// Limited to range of timestamps - - -function relative_date($posted_date,$format = null) { +/** + * @brief Returns a relative date string. + * + * Implements "3 seconds ago" etc. + * Based on $posted_date, (UTC). + * Results relative to current timezone. + * Limited to range of timestamps. + * + * @param string $posted_date + * @param string $format (optional) parsed with sprintf() + * <tt>%1$d %2$s ago</tt>, e.g. 22 hours ago, 1 minute ago + * @return string with relative date + */ +function relative_date($posted_date, $format = null) { - $localtime = datetime_convert('UTC',date_default_timezone_get(),$posted_date); + $localtime = datetime_convert('UTC', date_default_timezone_get(), $posted_date); $abs = strtotime($localtime); - - if (is_null($posted_date) || $posted_date === NULL_DATE || $abs === False) { - return t('never'); + + if (is_null($posted_date) || $posted_date === NULL_DATE || $abs === false) { + return t('never'); } $etime = time() - $abs; - + if ($etime < 1) { return t('less than a second ago'); } - + $a = array( 12 * 30 * 24 * 60 * 60 => array( t('year'), t('years')), 30 * 24 * 60 * 60 => array( t('month'), t('months')), 7 * 24 * 60 * 60 => array( t('week'), t('weeks')), @@ -247,231 +276,256 @@ function relative_date($posted_date,$format = null) { 60 => array( t('minute'), t('minutes')), 1 => array( t('second'), t('seconds')) ); - + foreach ($a as $secs => $str) { $d = $etime / $secs; if ($d >= 1) { $r = round($d); - // translators - e.g. 22 hours ago, 1 minute ago - if(! $format) - $format = t('%1$d %2$s ago'); - return sprintf( $format,$r, (($r == 1) ? $str[0] : $str[1])); - } - } -} - + if (! $format) + $format = t('%1$d %2$s ago', 'e.g. 22 hours ago, 1 minute ago'); + return sprintf($format, $r, (($r == 1) ? $str[0] : $str[1])); + } + } +} -// Returns age in years, given a date of birth, -// the timezone of the person whose date of birth is provided, -// and the timezone of the person viewing the result. -// Why? Bear with me. Let's say I live in Mittagong, Australia, and my -// birthday is on New Year's. You live in San Bruno, California. -// When exactly are you going to see my age increase? -// A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start -// celebrating and become a year older. If you wish me happy birthday -// on January 1 (San Bruno time), you'll be a day late. - -function age($dob,$owner_tz = '',$viewer_tz = '') { - if(! intval($dob)) +/** + * @brief Returns timezone correct age in years. + * + * Returns the age in years, given a date of birth, the timezone of the person + * whose date of birth is provided, and the timezone of the person viewing the + * result. + * + * Why? Bear with me. Let's say I live in Mittagong, Australia, and my birthday + * is on New Year's. You live in San Bruno, California. + * When exactly are you going to see my age increase? + * + * A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start celebrating + * and become a year older. If you wish me happy birthday on January 1 + * (San Bruno time), you'll be a day late. + * + * @param string $dob Date of Birth + * @param string $owner_tz (optional) timezone of the person of interest + * @param string $viewer_tz (optional) timezone of the person viewing + * @return number + */ +function age($dob, $owner_tz = '', $viewer_tz = '') { + if (! intval($dob)) return 0; - if(! $owner_tz) + if (! $owner_tz) $owner_tz = date_default_timezone_get(); - if(! $viewer_tz) + if (! $viewer_tz) $viewer_tz = date_default_timezone_get(); - $birthdate = datetime_convert('UTC',$owner_tz,$dob . ' 00:00:00+00:00','Y-m-d'); - list($year,$month,$day) = explode("-",$birthdate); - $year_diff = datetime_convert('UTC',$viewer_tz,'now','Y') - $year; - $curr_month = datetime_convert('UTC',$viewer_tz,'now','m'); - $curr_day = datetime_convert('UTC',$viewer_tz,'now','d'); + $birthdate = datetime_convert('UTC', $owner_tz, $dob . ' 00:00:00+00:00','Y-m-d'); + list($year,$month,$day) = explode("-", $birthdate); + $year_diff = datetime_convert('UTC', $viewer_tz, 'now', 'Y') - $year; + $curr_month = datetime_convert('UTC', $viewer_tz, 'now', 'm'); + $curr_day = datetime_convert('UTC', $viewer_tz, 'now', 'd'); - if(($curr_month < $month) || (($curr_month == $month) && ($curr_day < $day))) + if (($curr_month < $month) || (($curr_month == $month) && ($curr_day < $day))) $year_diff--; + return $year_diff; } +/** + * @brief Get days of a month in a given year. + * + * Returns number of days in the month of the given year. + * $m = 1 is 'January' to match human usage. + * + * @param int $y year + * @param int $m month (1=January, 12=December) + * @return int number of days in the given month + */ +function get_dim($y, $m) { + $dim = array( 0, + 31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31 + ); + if ($m != 2) + return $dim[$m]; -// Get days in month -// get_dim($year, $month); -// returns number of days. -// $month[1] = 'January'; -// to match human usage. - - -function get_dim($y,$m) { + if (((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0)) + return 29; - $dim = array( 0, - 31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31); - - if($m != 2) - return $dim[$m]; - if(((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0)) - return 29; - return $dim[2]; + return $dim[2]; } +/** + * @brief Returns the first day in month for a given month, year. + * + * Months start at 1. + * + * @param int $y Year + * @param int $m Month (1=January, 12=December) + * @return day 0 = Sunday through 6 = Saturday + */ +function get_first_dim($y, $m) { + $d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m)); -// Returns the first day in month for a given month, year -// get_first_dim($year,$month) -// returns 0 = Sunday through 6 = Saturday -// Months start at 1. - - -function get_first_dim($y,$m) { - $d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m)); - return datetime_convert('UTC','UTC',$d,'w'); + return datetime_convert('UTC', 'UTC', $d, 'w'); } -// output a calendar for the given month, year. -// if $links are provided (array), e.g. $links[12] => 'http://mylink' , -// date 12 will be linked appropriately. Today's date is also noted by -// altering td class. -// Months count from 1. - - -// TODO: provide (prev,next) links, define class variations for different size calendars - -function cal($y = 0,$m = 0, $links = false, $class='') { - +/** + * @brief Output a calendar for the given month, year. + * + * If $links are provided (array), e.g. $links[12] => 'http://mylink' , + * date 12 will be linked appropriately. Today's date is also noted by + * altering td class. + * Months count from 1. + * + * @param number $y Year + * @param number $m Month + * @param string $links (default false) + * @param string $class + * @return string + * + * @todo provide (prev,next) links, define class variations for different size calendars + */ +function cal($y = 0, $m = 0, $links = false, $class='') { // month table - start at 1 to match human usage. $mtab = array(' ', - 'January','February','March', - 'April','May','June', - 'July','August','September', - 'October','November','December' - ); + 'January','February','March', + 'April','May','June', + 'July','August','September', + 'October','November','December' + ); $thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y'); $thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m'); - if(! $y) + if (! $y) $y = $thisyear; - if(! $m) + if (! $m) $m = intval($thismonth); - $dn = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); - $f = get_first_dim($y,$m); - $l = get_dim($y,$m); - $d = 1; - $dow = 0; - $started = false; + $dn = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); + $f = get_first_dim($y, $m); + $l = get_dim($y, $m); + $d = 1; + $dow = 0; + $started = false; - if(($y == $thisyear) && ($m == $thismonth)) - $tddate = intval(datetime_convert('UTC',date_default_timezone_get(),'now','j')); + if (($y == $thisyear) && ($m == $thismonth)) + $tddate = intval(datetime_convert('UTC',date_default_timezone_get(),'now','j')); $str_month = day_translate($mtab[$m]); - $o = '<table class="calendar' . $class . '">'; - $o .= "<caption>$str_month $y</caption><tr>"; - for($a = 0; $a < 7; $a ++) - $o .= '<th>' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '</th>'; - $o .= '</tr><tr>'; - - while($d <= $l) { - if(($dow == $f) && (! $started)) - $started = true; - $today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : ''); - $o .= "<td $today>"; - $day = str_replace(' ',' ',sprintf('%2.2d', $d)); - if($started) { - if(is_array($links) && isset($links[$d])) - $o .= "<a href=\"{$links[$d]}\">$day</a>"; - else - $o .= $day; - $d ++; - } - else - $o .= ' '; - $o .= '</td>'; - $dow ++; - if(($dow == 7) && ($d <= $l)) { - $dow = 0; - $o .= '</tr><tr>'; - } - } - if($dow) - for($a = $dow; $a < 7; $a ++) - $o .= '<td> </td>'; - $o .= '</tr></table>'."\r\n"; - - return $o; -} + $o = '<table class="calendar' . $class . '">'; + $o .= "<caption>$str_month $y</caption><tr>"; + for ($a = 0; $a < 7; $a ++) + $o .= '<th>' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '</th>'; + + $o .= '</tr><tr>'; + + while ($d <= $l) { + if (($dow == $f) && (! $started)) + $started = true; + + $today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : ''); + $o .= "<td $today>"; + $day = str_replace(' ',' ',sprintf('%2.2d', $d)); + if ($started) { + if (is_array($links) && isset($links[$d])) + $o .= "<a href=\"{$links[$d]}\">$day</a>"; + else + $o .= $day; + + $d ++; + } else { + $o .= ' '; + } + + $o .= '</td>'; + $dow ++; + if (($dow == 7) && ($d <= $l)) { + $dow = 0; + $o .= '</tr><tr>'; + } + } + if ($dow) + for ($a = $dow; $a < 7; $a ++) + $o .= '<td> </td>'; + + $o .= '</tr></table>'."\r\n"; + return $o; +} /** - * Return the next birthday, converted from the owner's timezone to UTC. + * @brief Return the next birthday, converted from the owner's timezone to UTC. + * * This makes it globally portable. * If the provided birthday lacks a month and or day, return an empty string. * A missing year is acceptable. + * + * @param string $dob Date of Birth + * @param string $tz Timezone + * @param string $format + * @return string */ +function z_birthday($dob, $tz, $format="Y-m-d H:i:s") { - -function z_birthday($dob,$tz,$format="Y-m-d H:i:s") { - - if(! strlen($tz)) + if (! strlen($tz)) $tz = 'UTC'; $birthday = ''; $tmp_dob = substr($dob,5); $tmp_d = substr($dob,8); - if(intval($tmp_dob) && intval($tmp_d)) { + if (intval($tmp_dob) && intval($tmp_d)) { $y = datetime_convert($tz,$tz,'now','Y'); $bd = $y . '-' . $tmp_dob . ' 00:00'; $t_dob = strtotime($bd); $now = strtotime(datetime_convert($tz,$tz,'now')); - if($t_dob < $now) + if ($t_dob < $now) $bd = $y + 1 . '-' . $tmp_dob . ' 00:00'; + $birthday = datetime_convert($tz,'UTC',$bd,$format); } return $birthday; - } /** + * @brief Create a birthday event for any connections with a birthday in the next 1-2 weeks. * - * Create a birthday event for any connections with a birthday in the next 1-2 weeks. * Update the year so that we don't create another event until next year. - * */ - - function update_birthdays() { require_once('include/event.php'); require_once('include/permissions.php'); - $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash + $r = q("SELECT * FROM abook left join xchan on abook_xchan = xchan_hash WHERE abook_dob > %s + interval %s and abook_dob < %s + interval %s", db_utcnow(), db_quoteinterval('7 day'), db_utcnow(), db_quoteinterval('14 day') - ); - if($r) { - foreach($r as $rr) { - - if(! perm_is_allowed($rr['abook_channel'],$rr['xchan_hash'],'send_stream')) + ); + if ($r) { + foreach ($r as $rr) { + if (! perm_is_allowed($rr['abook_channel'], $rr['xchan_hash'], 'send_stream')) continue; $ev = array(); $ev['uid'] = $rr['abook_channel']; $ev['account'] = $rr['abook_account']; $ev['event_xchan'] = $rr['xchan_hash']; - $ev['start'] = datetime_convert('UTC','UTC', $rr['abook_dob']); - $ev['finish'] = datetime_convert('UTC','UTC', $rr['abook_dob'] . ' + 1 day '); + $ev['start'] = datetime_convert('UTC', 'UTC', $rr['abook_dob']); + $ev['finish'] = datetime_convert('UTC', 'UTC', $rr['abook_dob'] . ' + 1 day '); $ev['adjust'] = 1; - $ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']); - $ev['description'] = sprintf( t('Happy Birthday %1$s'), + $ev['summary'] = sprintf( t('%1$s\'s birthday'), $rr['xchan_name']); + $ev['description'] = sprintf( t('Happy Birthday %1$s'), '[zrl=' . $rr['xchan_url'] . ']' . $rr['xchan_name'] . '[/zrl]') ; $ev['type'] = 'birthday'; - + $z = event_store_event($ev); - if($z) { - $item_id = event_store_item($ev,$z); + if ($z) { + $item_id = event_store_item($ev, $z); q("update abook set abook_dob = '%s' where abook_id = %d", - dbesc(intval($rr['abook_dob']) + 1 . substr($rr['abook_dob'],4)), + dbesc(intval($rr['abook_dob']) + 1 . substr($rr['abook_dob'], 4)), intval($rr['abook_id']) ); } diff --git a/include/dir_fns.php b/include/dir_fns.php index 4c6c40f15..d1e26b637 100644 --- a/include/dir_fns.php +++ b/include/dir_fns.php @@ -1,14 +1,23 @@ -<?php /** @file */ +<?php +/** + * @file include/dir_fns.php + */ require_once('include/permissions.php'); +/** + * @brief + * + * @param int $dirmode + * @return array + */ function find_upstream_directory($dirmode) { global $DIRECTORY_FALLBACK_SERVERS; $preferred = get_config('system','directory_server'); - if(! $preferred) { + if (! $preferred) { - /** + /* * No directory has yet been set. For most sites, pick one at random * from our list of directory servers. However, if we're a directory * server ourself, point at the local instance @@ -18,41 +27,40 @@ function find_upstream_directory($dirmode) { */ $dirmode = intval(get_config('system','directory_mode')); - if($dirmode == DIRECTORY_MODE_NORMAL) { + if ($dirmode == DIRECTORY_MODE_NORMAL) { $toss = mt_rand(0,count($DIRECTORY_FALLBACK_SERVERS)); $preferred = $DIRECTORY_FALLBACK_SERVERS[$toss]; set_config('system','directory_server',$preferred); - } - else{ + } else{ set_config('system','directory_server',z_root()); } } + return array('url' => $preferred); } +/** + * Directories may come and go over time. We will need to check that our + * directory server is still valid occasionally, and reset to something that + * is if our directory has gone offline for any reason + */ function check_upstream_directory() { - /** - * Directories may come and go over time. We will need to check that our - * directory server is still valid occasionally, and reset to something that - * is if our directory has gone offline for any reason - */ - - $directory = get_config('system','directory_server'); + $directory = get_config('system', 'directory_server'); // it's possible there is no directory server configured and the local hub is being used. // If so, default to preserving the absence of a specific server setting. - $isadir = true; + $isadir = true; - if($directory) { + if ($directory) { $h = parse_url($directory); - if($h) { + if ($h) { $x = zot_finger('[system]@' . $h['host']); - if($x['success']) { - $j = json_decode($x['body'],true); - if(array_key_exists('site',$j) && array_key_exists('directory_mode',$j['site'])) { - if($j['site']['directory_mode'] === 'normal') { + if ($x['success']) { + $j = json_decode($x['body'], true); + if (array_key_exists('site', $j) && array_key_exists('directory_mode', $j['site'])) { + if ($j['site']['directory_mode'] === 'normal') { $isadir = false; } } @@ -60,9 +68,8 @@ function check_upstream_directory() { } } - if(! $isadir) - set_config('system','directory_server',''); - return; + if (! $isadir) + set_config('system', 'directory_server', ''); } function get_globaldir_setting($observer) { @@ -95,12 +102,8 @@ function get_safemode_setting($observer) { } /** - * @function dir_sort_links() - * Called by the directory_sort widget + * @brief Called by the directory_sort widget. */ - - - function dir_sort_links() { $safe_mode = 1; @@ -110,7 +113,7 @@ function dir_sort_links() { $safe_mode = get_safemode_setting($observer); $globaldir = get_globaldir_setting($observer); - // Build urls without order and pubforums so it's easy to tack on the changed value + // Build urls without order and pubforums so it's easy to tack on the changed value // Probably there's an easier way to do this $current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : 'date'); @@ -145,38 +148,34 @@ function dir_sort_links() { '$pubforums' => array('pubforums', t('Public Forums Only'),(x($_REQUEST,'pubforums') ? $_REQUEST['pubforums'] : ''),'','',' onchange=\'window.location.href="' . $forumsurl . '&pubforums="+(this.checked ? 1 : 0)\''), '$globaldir' => array('globaldir', t('This Website Only'), 1-intval($globaldir),'','',' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''), )); + return $o; } - /** - * @function sync_directories($mode) - * - * @param int $mode; + * @brief Checks the directory mode of this hub. * * Checks the directory mode of this hub to see if it is some form of directory server. If it is, * get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request * a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB. * In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored - * directly if the rater's signature matches. + * directly if the rater's signature matches. * + * @param int $dirmode; */ - - function sync_directories($dirmode) { - if($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL) + if ($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL) return; $realm = get_directory_realm(); - if($realm == DIRECTORY_REALM) { + if ($realm == DIRECTORY_REALM) { $r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and ( site_realm = '%s' or site_realm = '') ", intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), dbesc(z_root()), dbesc($realm) ); - } - else { + } else { $r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' ", intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), dbesc(z_root()), @@ -185,9 +184,9 @@ function sync_directories($dirmode) { } // If there are no directory servers, setup the fallback master - // FIXME - what to do if we're in a different realm? + /** @FIXME What to do if we're in a different realm? */ - if((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) { + if ((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) { $r = array(); $r[] = array( 'site_url' => DIRECTORY_FALLBACK_MASTER, @@ -211,32 +210,30 @@ function sync_directories($dirmode) { intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY), dbesc(z_root()) ); - - } - if(! $r) + } + if (! $r) return; - foreach($r as $rr) { - if(! $rr['site_directory']) + foreach ($r as $rr) { + if (! $rr['site_directory']) continue; logger('sync directories: ' . $rr['site_directory']); // for brand new directory servers, only load the last couple of days. // It will take about a month for a new directory to obtain the full current repertoire of channels. - // FIXME - go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. + /** @FIXME Go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. */ $token = get_config('system','realm_token'); - $syncdate = (($rr['site_sync'] === NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']); $x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : '')); - if(! $x['success']) + if (! $x['success']) continue; $j = json_decode($x['body'],true); - if(!($j['transactions']) || ($j['ratings'])) + if (!($j['transactions']) || ($j['ratings'])) continue; q("update site set site_sync = '%s' where site_url = '%s'", @@ -246,17 +243,18 @@ function sync_directories($dirmode) { logger('sync_directories: ' . $rr['site_url'] . ': ' . print_r($j,true), LOGGER_DATA); - if(is_array($j['transactions']) && count($j['transactions'])) { - foreach($j['transactions'] as $t) { + if (is_array($j['transactions']) && count($j['transactions'])) { + foreach ($j['transactions'] as $t) { $r = q("select * from updates where ud_guid = '%s' limit 1", dbesc($t['transaction_id']) ); if($r) continue; + $ud_flags = 0; - if(is_array($t['flags']) && in_array('deleted',$t['flags'])) + if (is_array($t['flags']) && in_array('deleted',$t['flags'])) $ud_flags |= UPDATE_FLAGS_DELETED; - if(is_array($t['flags']) && in_array('forced',$t['flags'])) + if (is_array($t['flags']) && in_array('forced',$t['flags'])) $ud_flags |= UPDATE_FLAGS_FORCED; $z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) @@ -269,42 +267,41 @@ function sync_directories($dirmode) { ); } } - if(is_array($j['ratings']) && count($j['ratings'])) { - foreach($j['ratings'] as $rr) { + if (is_array($j['ratings']) && count($j['ratings'])) { + foreach ($j['ratings'] as $rr) { $x = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1", dbesc($rr['channel']), dbesc($rr['target']) ); - if($x && $x[0]['xlink_updated'] >= $rr['edited']) + if ($x && $x[0]['xlink_updated'] >= $rr['edited']) continue; // Ratings are signed by the rater. We need to verify before we can accept it. - // TODO - queue or defer if the xchan is not yet present on our site + /** @TODO Queue or defer if the xchan is not yet present on our site */ $y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", dbesc($rr['channel']) ); - if(! $y) { + if (! $y) { logger('key unavailable on this site for ' . $rr['channel']); continue; } - if(! rsa_verify($rr['target'] . '.' . $rr['rating'] . '.' . $rr['rating_text'], base64url_decode($rr['signature']),$y[0]['xchan_pubkey'])) { - logger('failed to verify rating'); + if (! rsa_verify($rr['target'] . '.' . $rr['rating'] . '.' . $rr['rating_text'], base64url_decode($rr['signature']),$y[0]['xchan_pubkey'])) { + logger('failed to verify rating'); continue; } - if($x) { + if ($x) { $z = q("update xlink set xlink_rating = %d, xlink_rating_text = '%s', xlink_sig = '%s', xlink_updated = '%s' where xlink_id = %d", intval($rr['rating']), dbesc($rr['rating_text']), dbesc($rr['signature']), dbesc(datetime_convert()), intval($x[0]['xlink_id']) - ); - logger('rating updated'); - } - else { - $z = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", + ); + logger('rating updated'); + } else { + $z = q("insert into xlink ( xlink_xchan, xlink_link, xlink_rating, xlink_rating_text, xlink_sig, xlink_updated, xlink_static ) values( '%s', '%s', %d, '%s', '%s', '%s', 1 ) ", dbesc($rr['channel']), dbesc($rr['target']), intval($rr['rating']), @@ -321,50 +318,51 @@ function sync_directories($dirmode) { /** - * $function update_directory_entry($ud) + * @brief * - * @param array $ud; // Entry from update table - * Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data + * Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data. * - * Ignore updating records marked as deleted + * Ignore updating records marked as deleted. * - * If successful, - * sets ud_last in the DB to the current datetime for this reddress/webbie + * If successful, sets ud_last in the DB to the current datetime for this + * reddress/webbie. + * + * @param array $ud Entry from update table */ - function update_directory_entry($ud) { logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA); - if($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) { + if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) { $success = false; - $x = zot_finger($ud['ud_addr'],''); - if($x['success']) { - $j = json_decode($x['body'],true); - if($j) + $x = zot_finger($ud['ud_addr'], ''); + if ($x['success']) { + $j = json_decode($x['body'], true); + if ($j) $success = true; - $y = import_xchan($j,0,$ud); + + $y = import_xchan($j, 0, $ud); } - if(! $success) { - $r = q("update updates set ud_last = '%s' where ud_addr = '%s'", + if (! $success) { + q("update updates set ud_last = '%s' where ud_addr = '%s'", dbesc(datetime_convert()), dbesc($ud['ud_addr']) ); } } - } /** - * @function local_dir_update($uid,$force) - * push local channel updates to a local directory server - * This is called from include/directory.php if a profile is to be pushed - * to the directory and the local hub in this case is any kind of directory server. + * @brief Push local channel updates to a local directory server. * + * This is called from include/directory.php if a profile is to be pushed to the + * directory and the local hub in this case is any kind of directory server. + * + * @param int $uid + * @param boolean $force */ - -function local_dir_update($uid,$force) { +function local_dir_update($uid, $force) { logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG); @@ -375,12 +373,12 @@ function local_dir_update($uid,$force) { $profile = array(); $profile['encoding'] = 'zot'; - if($p) { + if ($p) { $hash = $p[0]['channel_hash']; $profile['description'] = $p[0]['pdesc']; $profile['birthday'] = $p[0]['dob']; - if($age = age($p[0]['dob'],$p[0]['channel_timezone'],'')) + if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],'')) $profile['age'] = $age; $profile['gender'] = $p[0]['gender']; @@ -394,14 +392,15 @@ function local_dir_update($uid,$force) { $profile['homepage'] = $p[0]['homepage']; $profile['hometown'] = $p[0]['hometown']; - if($p[0]['keywords']) { + if ($p[0]['keywords']) { $tags = array(); - $k = explode(' ',$p[0]['keywords']); - if($k) - foreach($k as $kk) - if(trim($kk)) + $k = explode(' ', $p[0]['keywords']); + if ($k) + foreach ($k as $kk) + if (trim($kk)) $tags[] = trim($kk); - if($tags) + + if ($tags) $profile['keywords'] = $tags; } @@ -414,26 +413,23 @@ function local_dir_update($uid,$force) { ); // Be careful - XCHAN_FLAGS_HIDDEN should evaluate to 1 - if(($r[0]['xchan_flags'] & XCHAN_FLAGS_HIDDEN) != $hidden) + if (($r[0]['xchan_flags'] & XCHAN_FLAGS_HIDDEN) != $hidden) $new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_HIDDEN; else $new_flags = $r[0]['xchan_flags']; - - if($new_flags != $r[0]['xchan_flags']) { + if ($new_flags != $r[0]['xchan_flags']) { $r = q("update xchan set xchan_flags = %d where xchan_hash = '%s'", intval($new_flags), dbesc($p[0]['channel_hash']) ); - } $address = $p[0]['channel_address'] . '@' . get_app()->get_hostname(); - if(perm_is_allowed($uid,'','view_profile')) { - import_directory_profile($hash,$profile,$address,0); - } - else { + if (perm_is_allowed($uid, '', 'view_profile')) { + import_directory_profile($hash, $profile, $address, 0); + } else { // they may have made it private $r = q("delete from xprof where xprof_hash = '%s'", dbesc($hash) @@ -445,7 +441,5 @@ function local_dir_update($uid,$force) { } $ud_hash = random_string() . '@' . get_app()->get_hostname(); - update_modtime($hash,$ud_hash,$p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED)); - + update_modtime($hash, $ud_hash, $p[0]['channel_address'] . '@' . get_app()->get_hostname(),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED)); } - diff --git a/include/directory.php b/include/directory.php index 801d4ec8e..9ab1d805b 100644 --- a/include/directory.php +++ b/include/directory.php @@ -1,14 +1,23 @@ -<?php /** @file */ +<?php +/** + * @file include/directory.php + * @brief executes directory_run() + */ require_once('boot.php'); require_once('include/zot.php'); require_once('include/cli_startup.php'); require_once('include/dir_fns.php'); - +/** + * @brief + * + * @param array $argv + * @param array $argc + */ function directory_run($argv, $argc){ - cli_startup(); + cli_startup(); if($argc < 2) return; @@ -37,7 +46,6 @@ function directory_run($argv, $argc){ $channel = $x[0]; - if($dirmode != DIRECTORY_MODE_NORMAL) { // this is an in-memory update and we don't need to send a network packet. @@ -70,8 +78,9 @@ function directory_run($argv, $argc){ if(! $z['success']) { - // FIXME - we aren't updating channel_dirdate if we have to queue - // the directory packet. That means we'll try again on the next poll run. + /** @FIXME we aren't updating channel_dirdate if we have to queue + * the directory packet. That means we'll try again on the next poll run. + */ $hash = random_string(); q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_created, outq_updated, outq_notify, outq_msg ) @@ -87,8 +96,7 @@ function directory_run($argv, $argc){ dbesc($packet), dbesc('') ); - } - else { + } else { q("update channel set channel_dirdate = '%s' where channel_id = %d", dbesc(datetime_convert()), intval($channel['channel_id']) @@ -101,7 +109,7 @@ function directory_run($argv, $argc){ } -if (array_search(__file__,get_included_files())===0){ - directory_run($argv,$argc); - killme(); +if (array_search(__file__, get_included_files()) === 0) { + directory_run($argv, $argc); + killme(); } diff --git a/include/enotify.php b/include/enotify.php index 36d457c10..e801c3100 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -1,33 +1,50 @@ -<?php /** @file */ - +<?php +/** + * @file include/enotify.php + * + * @brief File with functions and a class for email notifications. + */ + +/** + * @brief + * + * @param array $params an assoziative array with: + * * \e string \b from_xchan sender xchan hash + * * \e string \b to_xchan recipient xchan hash + * * \e array \b item an assoziative array + * * \e int \b type one of the NOTIFY_* constants from boot.php + * * \e string \b link + * * \e string \b parent_mid + * * \e string \b otype + * * \e string \b verb + * * \e string \b activity + */ function notification($params) { logger('notification: entry', LOGGER_DEBUG); // throw a small amount of entropy into the system to breakup duplicates arriving at the same precise instant. - usleep(mt_rand(0,10000)); - + usleep(mt_rand(0, 10000)); $a = get_app(); - if($params['from_xchan']) { + if ($params['from_xchan']) { $x = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($params['from_xchan']) ); } - if($params['to_xchan']) { + if ($params['to_xchan']) { $y = q("select channel.*, account.* from channel left join account on channel_account_id = account_id where channel_hash = '%s' and not (channel_pageflags & %d)>0 limit 1", dbesc($params['to_xchan']), intval(PAGE_REMOVED) ); } - if($x & $y) { + if ($x & $y) { $sender = $x[0]; $recip = $y[0]; - } - else { + } else { logger('notification: no sender or recipient.'); logger('sender: ' . $params['from_xchan']); logger('recip: ' . $params['to_xchan']); @@ -55,10 +72,10 @@ function notification($params) { $additional_mail_header = ""; - if(array_key_exists('item',$params)) { + if (array_key_exists('item', $params)) { require_once('include/conversation.php'); // if it's a normal item... - if(array_key_exists('verb',$params['item'])) { + if (array_key_exists('verb', $params['item'])) { // localize_item() alters the original item so make a copy first $i = $params['item']; logger('calling localize'); @@ -66,13 +83,11 @@ function notification($params) { $title = $i['title']; $body = $i['body']; $private = (($i['item_private']) || ($i['item_flags'] & ITEM_OBSCURED)); - } - else { + } else { $title = $params['item']['title']; $body = $params['item']['body']; } - } - else { + } else { $title = $body = ''; } @@ -80,7 +95,7 @@ function notification($params) { // e.g. "your post", "David's photo", etc. $possess_desc = t('%s <!item_type!>'); - if($params['type'] == NOTIFY_MAIL) { + if ($params['type'] == NOTIFY_MAIL) { logger('notification: mail'); $subject = sprintf( t('[Red:Notify] New mail received at %s'),$sitename); @@ -92,28 +107,27 @@ function notification($params) { $itemlink = $siteurl . '/mail/' . $params['item']['id']; } - if($params['type'] == NOTIFY_COMMENT) { + if ($params['type'] == NOTIFY_COMMENT) { // logger("notification: params = " . print_r($params, true), LOGGER_DEBUG); $itemlink = $params['link']; - // ignore like/unlike activity on posts - they probably require a sepearate notification preference - if(array_key_exists('item',$params) && (! visible_activity($params['item']))) + if (array_key_exists('item',$params) && (! visible_activity($params['item']))) return; $parent_mid = $params['parent_mid']; // Check to see if there was already a notify for this post. // If so don't create a second notification - + $p = null; $p = q("select id from notify where link = '%s' and uid = %d limit 1", dbesc($params['link']), intval($recip['channel_id']) ); - if($p) { + if ($p) { logger('notification: comment already notified'); pop_lang(); return; @@ -182,26 +196,26 @@ function notification($params) { $subject = sprintf( t('[Red:Notify] %s posted to your profile wall') , $sender['xchan_name']); $preamble = sprintf( t('%1$s, %2$s posted to your profile wall at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename); - + $epreamble = sprintf( t('%1$s, %2$s posted to [zrl=%3$s]your wall[/zrl]') , $recip['channel_name'], '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]', $params['link']); - + $sitelink = t('Please visit %s to view and/or reply to the conversation.'); $tsitelink = sprintf( $sitelink, $siteurl ); $hsitelink = sprintf( $sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>'); $itemlink = $params['link']; } - if($params['type'] == NOTIFY_TAGSELF) { + if ($params['type'] == NOTIFY_TAGSELF) { $p = null; $p = q("select id from notify where link = '%s' and uid = %d limit 1", dbesc($params['link']), intval($recip['channel_id']) ); - if($p) { + if ($p) { logger('enotify: tag: already notified about this post'); pop_lang(); return; @@ -220,8 +234,7 @@ function notification($params) { $itemlink = $params['link']; } - if($params['type'] == NOTIFY_POKE) { - + if ($params['type'] == NOTIFY_POKE) { $subject = sprintf( t('[Red:Notify] %1$s poked you') , $sender['xchan_name']); $preamble = sprintf( t('%1$s, %2$s poked you at %3$s') , $recip['channel_name'], $sender['xchan_name'], $sitename); $epreamble = sprintf( t('%1$s, %2$s [zrl=%2$s]poked you[/zrl].') , @@ -239,7 +252,7 @@ function notification($params) { $itemlink = $params['link']; } - if($params['type'] == NOTIFY_TAGSHARE) { + if ($params['type'] == NOTIFY_TAGSHARE) { $subject = sprintf( t('[Red:Notify] %s tagged your post') , $sender['xchan_name']); $preamble = sprintf( t('%1$s, %2$s tagged your post at %3$s') , $recip['channel_name'],$sender['xchan_name'], $sitename); $epreamble = sprintf( t('%1$s, %2$s tagged [zrl=%3$s]your post[/zrl]') , @@ -253,7 +266,7 @@ function notification($params) { $itemlink = $params['link']; } - if($params['type'] == NOTIFY_INTRO) { + if ($params['type'] == NOTIFY_INTRO) { $subject = sprintf( t('[Red:Notify] Introduction received')); $preamble = sprintf( t('%1$s, you\'ve received an new connection request from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename); $epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a new connection request[/zrl] from %3$s.'), @@ -268,7 +281,7 @@ function notification($params) { $itemlink = $params['link']; } - if($params['type'] == NOTIFY_SUGGEST) { + if ($params['type'] == NOTIFY_SUGGEST) { $subject = sprintf( t('[Red:Notify] Friend suggestion received')); $preamble = sprintf( t('%1$s, you\'ve received a friend suggestion from \'%2$s\' at %3$s'), $recip['channel_name'], $sender['xchan_name'], $sitename); $epreamble = sprintf( t('%1$s, you\'ve received [zrl=%2$s]a friend suggestion[/zrl] for %3$s from %4$s.'), @@ -276,7 +289,7 @@ function notification($params) { $itemlink, '[zrl=' . $params['item']['url'] . ']' . $params['item']['name'] . '[/zrl]', '[zrl=' . $sender['xchan_url'] . ']' . $sender['xchan_name'] . '[/zrl]'); - + $body = t('Name:') . ' ' . $params['item']['name'] . "\n"; $body .= t('Photo:') . ' ' . $params['item']['photo'] . "\n"; $body .= sprintf( t('You may visit their profile at %s'),$params['item']['url']); @@ -287,27 +300,27 @@ function notification($params) { $itemlink = $params['link']; } - if($params['type'] == NOTIFY_CONFIRM) { - + if ($params['type'] == NOTIFY_CONFIRM) { + // ? } - if($params['type'] == NOTIFY_SYSTEM) { - + if ($params['type'] == NOTIFY_SYSTEM) { + // ? } $h = array( - 'params' => $params, + 'params' => $params, 'subject' => $subject, - 'preamble' => $preamble, - 'epreamble' => $epreamble, - 'body' => $body, + 'preamble' => $preamble, + 'epreamble' => $epreamble, + 'body' => $body, 'sitelink' => $sitelink, 'tsitelink' => $tsitelink, 'hsitelink' => $hsitelink, 'itemlink' => $itemlink ); - - call_hooks('enotify',$h); + + call_hooks('enotify', $h); $subject = $h['subject']; $preamble = $h['preamble']; @@ -319,16 +332,16 @@ function notification($params) { $itemlink = $h['itemlink']; - require_once('include/html2bbcode.php'); + require_once('include/html2bbcode.php'); do { $dups = false; $hash = random_string(); - $r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1", + $r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1", dbesc($hash)); - if(count($r)) + if (count($r)) $dups = true; - } while($dups == true); + } while ($dups === true); $datarray = array(); @@ -348,10 +361,10 @@ function notification($params) { $datarray['abort'] = false; $datarray['item'] = $params['item']; - + call_hooks('enotify_store', $datarray); - if($datarray['abort']) { + if ($datarray['abort']) { pop_lang(); return; } @@ -365,8 +378,8 @@ function notification($params) { // So easiest solution to hide them from Notices is to mark them as seen right away. // Another option would be to not add them to the DB, and change how emails are handled (probably would be better that way) $always_show_in_notices = get_pconfig($recip['channel_id'],'system','always_show_in_notices'); - if(!$always_show_in_notices) { - if(($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) { + if (!$always_show_in_notices) { + if (($params['type'] == NOTIFY_WALL) || ($params['type'] == NOTIFY_MAIL) || ($params['type'] == NOTIFY_INTRO)) { $seen = 1; } } @@ -392,9 +405,9 @@ function notification($params) { dbesc($hash), intval($recip['channel_id']) ); - if($r) + if ($r) { $notify_id = $r[0]['id']; - else { + } else { logger('notification not found.'); pop_lang(); return; @@ -405,7 +418,7 @@ function notification($params) { // wretched hack, but we don't want to duplicate all the preamble variations and we also don't want to screw up a translation - if(($a->language === 'en' || (! $a->language)) && strpos($msg,', ')) + if (($a->language === 'en' || (! $a->language)) && strpos($msg,', ')) $msg = substr($msg,strpos($msg,', ')+1); $r = q("update notify set msg = '%s' where id = %d and uid = %d", @@ -413,12 +426,11 @@ function notification($params) { intval($notify_id), intval($datarray['uid']) ); - // send email notification if notification preferences permit require_once('bbcode.php'); - if((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) { + if ((intval($recip['channel_notifyflags']) & intval($params['type'])) || $params['type'] == NOTIFY_SYSTEM) { logger('notification: sending notification email'); @@ -429,8 +441,6 @@ function notification($params) { return; } - - $textversion = strip_tags(html_entity_decode(bbcode(stripslashes(str_replace(array("\\r", "\\n"), array( "", "\n"), $body))),ENT_QUOTES,'UTF-8')); $htmlversion = bbcode(stripslashes(str_replace(array("\\r","\\n"), array("","<br />\n"),$body))); @@ -450,7 +460,6 @@ function notification($params) { unset($_SESSION['zid_override']); unset($_SESSION['zrl_override']); - $datarray = array(); $datarray['banner'] = $banner; $datarray['product'] = $product; @@ -485,13 +494,13 @@ function notification($params) { $private_activity = false; - if(! $datarray['email_secure']) { - switch($params['type']) { + if (! $datarray['email_secure']) { + switch ($params['type']) { case NOTIFY_WALL: case NOTIFY_TAGSELF: case NOTIFY_POKE: case NOTIFY_COMMENT: - if(! $private) + if (! $private) break; $private_activity = true; case NOTIFY_MAIL: @@ -503,11 +512,12 @@ function notification($params) { } } - if($private_activity - && intval(get_pconfig($datarray['uid'],'system','ignore_private_notifications'))) { + if ($private_activity + && intval(get_pconfig($datarray['uid'], 'system', 'ignore_private_notifications'))) { + pop_lang(); return; - } + } // load the template for private message notifications $tpl = get_markup_template('email_notify_html.tpl'); @@ -525,13 +535,13 @@ function notification($params) { '$hitemlink' => $datarray['hitemlink'], '$thanks' => $datarray['thanks'], '$site_admin' => $datarray['site_admin'], - '$title' => $datarray['title'], - '$htmlversion' => $datarray['htmlversion'], + '$title' => $datarray['title'], + '$htmlversion' => $datarray['htmlversion'], )); - + // load the template for private message notifications $tpl = get_markup_template('email_notify_text.tpl'); - $email_text_body = replace_macros($tpl,array( + $email_text_body = replace_macros($tpl, array( '$banner' => $datarray['banner'], '$product' => $datarray['product'], '$preamble' => $datarray['preamble'], @@ -545,8 +555,8 @@ function notification($params) { '$titemlink' => $datarray['titemlink'], '$thanks' => $datarray['thanks'], '$site_admin' => $datarray['site_admin'], - '$title' => $datarray['title'], - '$textversion' => $datarray['textversion'], + '$title' => $datarray['title'], + '$textversion' => $datarray['textversion'], )); // logger('text: ' . $email_text_body); @@ -570,41 +580,48 @@ function notification($params) { } +/** + * @brief A class for sending email notifications. + * + * @fixme Class names start mostly with capital letter to distinguish them easier. + */ class enotify { /** - * Send a multipart/alternative message with Text and HTML versions + * @brief Send a multipart/alternative message with Text and HTML versions. * - * @param fromName name of the sender - * @param fromEmail email fo the sender - * @param replyTo replyTo address to direct responses - * @param toEmail destination email address - * @param messageSubject subject of the message - * @param htmlVersion html version of the message - * @param textVersion text only version of the message - * @param additionalMailHeader additions to the smtp mail header + * @param array $params an assoziative 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 + * * \e string \b toEmail destination email address + * * \e string \b messageSubject subject of the message + * * \e string \b htmlVersion html version of the message + * * \e string \b textVersion text only version of the message + * * \e string \b additionalMailHeader additions to the smtp mail header */ static public function send($params) { $fromName = email_header_encode(html_entity_decode($params['fromName'],ENT_QUOTES,'UTF-8'),'UTF-8'); $messageSubject = email_header_encode(html_entity_decode($params['messageSubject'],ENT_QUOTES,'UTF-8'),'UTF-8'); - + // generate a mime boundary - $mimeBoundary =rand(0,9)."-" - .rand(10000000000,9999999999)."-" - .rand(10000000000,9999999999)."=:" - .rand(10000,99999); + $mimeBoundary = rand(0, 9) . "-" + .rand(10000000000, 9999999999) . "-" + .rand(10000000000, 9999999999) . "=:" + .rand(10000, 99999); // generate a multipart/alternative message header $messageHeader = $params['additionalMailHeader'] . - "From: $fromName <{$params['fromEmail']}>\n" . + "From: $fromName <{$params['fromEmail']}>\n" . "Reply-To: $fromName <{$params['replyTo']}>\n" . "MIME-Version: 1.0\n" . "Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\""; // assemble the final multipart message body with the text and html types included - $textBody = chunk_split(base64_encode($params['textVersion'])); - $htmlBody = chunk_split(base64_encode($params['htmlVersion'])); + $textBody = chunk_split(base64_encode($params['textVersion'])); + $htmlBody = chunk_split(base64_encode($params['htmlVersion'])); + $multipartMessageBody = "--" . $mimeBoundary . "\n" . // plain text section "Content-Type: text/plain; charset=UTF-8\n" . @@ -618,12 +635,11 @@ class enotify { // send the message $res = mail( - $params['toEmail'], // send to address + $params['toEmail'], // send to address $messageSubject, // subject - $multipartMessageBody, // message body + $multipartMessageBody, // message body $messageHeader // message headers ); logger("notification: enotify::send returns " . $res, LOGGER_DEBUG); } -} - +}
\ No newline at end of file diff --git a/include/event.php b/include/event.php index 1ed541d99..05f01535c 100644 --- a/include/event.php +++ b/include/event.php @@ -1,6 +1,14 @@ -<?php /** @file */ - - +<?php +/** + * @file include/event.php + */ + +/** + * @brief Returns an event as HTML + * + * @param array $ev + * @return string + */ function format_event_html($ev) { require_once('include/bbcode.php'); @@ -12,13 +20,12 @@ function format_event_html($ev) { $o = '<div class="vevent">' . "\r\n"; - $o .= '<p class="summary event-summary">' . bbcode($ev['summary']) . '</p>' . "\r\n"; $o .= '<p class="description event-description">' . bbcode($ev['description']) . '</p>' . "\r\n"; $o .= '<p class="event-start">' . t('Starts:') . ' <abbr class="dtstart" title="' - . datetime_convert('UTC','UTC',$ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )) + . datetime_convert('UTC', 'UTC', $ev['start'], (($ev['adjust']) ? ATOM_TIME : 'Y-m-d\TH:i:s' )) . '" >' . (($ev['adjust']) ? day_translate(datetime_convert('UTC', date_default_timezone_get(), $ev['start'] , $bd_format )) @@ -38,15 +45,15 @@ function format_event_html($ev) { if(strlen($ev['location'])) $o .= '<p class="event-location"> ' . t('Location:') . ' <span class="location">' - . bbcode($ev['location']) + . bbcode($ev['location']) . '</span></p>' . "\r\n"; $o .= '</div>' . "\r\n"; + return $o; } - function ical_wrapper($ev) { if(! ((is_array($ev)) && count($ev))) @@ -56,7 +63,7 @@ function ical_wrapper($ev) { $o .= "\nVERSION:2.0"; $o .= "\nMETHOD:PUBLISH"; $o .= "\nPRODID:-//" . get_config('system','sitename') . "//" . RED_PLATFORM . "//" . strtoupper(get_app()->language). "\n"; - if(array_key_exists('start',$ev)) + if(array_key_exists('start', $ev)) $o .= format_event_ical($ev); else { foreach($ev as $e) { @@ -84,13 +91,15 @@ function format_event_ical($ev) { if($ev['description']) $o .= "\nDESCRIPTION:" . format_ical_text($ev['description']); $o .= "\nEND:VEVENT\n"; + return $o; } -function format_ical_text($s) { +function format_ical_text($s) { require_once('include/bbcode.php'); require_once('include/html2plain.php'); + return(wordwrap(html2plain(bbcode($s)),72,"\n ",true)); } @@ -117,16 +126,16 @@ function format_event_bbcode($ev) { if($ev['adjust']) $o .= '[event-adjust]' . $ev['adjust'] . '[/event-adjust]'; - return $o; - } + function bbtovcal($s) { $o = ''; $ev = bbtoevent($s); if($ev['description']) $o = format_event_html($ev); + return $o; } @@ -154,27 +163,41 @@ function bbtoevent($s) { if(preg_match("/\[event\-adjust\](.*?)\[\/event\-adjust\]/is",$s,$match)) $ev['adjust'] = $match[1]; $ev['nofinish'] = (((x($ev, 'start') && $ev['start']) && (!x($ev, 'finish') || !$ev['finish'])) ? 1 : 0); - return $ev; + return $ev; } - +/** + * @brief Sorts the given array of events by date. + * + * @see ev_compare() + * @param array $arr + * @return sorted array + */ function sort_by_date($arr) { - if(is_array($arr)) - usort($arr,'ev_compare'); + if (is_array($arr)) + usort($arr, 'ev_compare'); + return $arr; } - -function ev_compare($a,$b) { +/** + * @brief Compare function for events. + * + * @see sort_by_date() + * @param array $a + * @param array $b + * @return number return values like strcmp() + */ +function ev_compare($a, $b) { $date_a = (($a['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$a['start']) : $a['start']); $date_b = (($b['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$b['start']) : $b['start']); - if($date_a === $date_b) - return strcasecmp($a['description'],$b['description']); - - return strcmp($date_a,$date_b); + if ($date_a === $date_b) + return strcasecmp($a['description'], $b['description']); + + return strcmp($date_a, $date_b); } @@ -182,11 +205,9 @@ function event_store_event($arr) { $arr['created'] = (($arr['created']) ? $arr['created'] : datetime_convert()); $arr['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert()); - $arr['type'] = (($arr['type']) ? $arr['type'] : 'event' ); + $arr['type'] = (($arr['type']) ? $arr['type'] : 'event' ); $arr['event_xchan'] = (($arr['event_xchan']) ? $arr['event_xchan'] : ''); - - // Existing event being modified if($arr['id'] || $arr['event_hash']) { @@ -206,7 +227,6 @@ function event_store_event($arr) { ); } - if(! $r) return false; @@ -216,7 +236,7 @@ function event_store_event($arr) { } $hash = $r[0]['event_hash']; - + // The event changed. Update it. $r = q("UPDATE `event` SET @@ -251,14 +271,12 @@ function event_store_event($arr) { intval($r[0]['id']), intval($arr['uid']) ); - } - else { + } else { - // New event. Store it. + // New event. Store it. $hash = random_string(); - $r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary,description,location,type, adjust,nofinish,allow_cid,allow_gid,deny_cid,deny_gid) VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' ) ", @@ -280,7 +298,6 @@ function event_store_event($arr) { dbesc($arr['allow_gid']), dbesc($arr['deny_cid']), dbesc($arr['deny_gid']) - ); } @@ -292,7 +309,6 @@ function event_store_event($arr) { return $r[0]; return false; - } function event_addtocal($item_id, $uid) { @@ -339,22 +355,21 @@ function event_addtocal($item_id, $uid) { intval($item['id']), intval($channel['channel_id']) ); + return true; } } + return false; } - -function event_store_item($arr,$event) { +function event_store_item($arr, $event) { require_once('include/datetime.php'); require_once('include/items.php'); require_once('include/bbcode.php'); - $a = get_app(); - $item = null; if($arr['mid'] && $arr['uid']) { @@ -370,28 +385,28 @@ function event_store_item($arr,$event) { $item_arr = array(); $prefix = ''; - $birthday = false; +// $birthday = false; if($event['type'] === 'birthday') { $prefix = t('This event has been added to your calendar.'); - $birthday = true; +// $birthday = true; // 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 // 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. + // and send them out from the source. This has its own issues. $item_arr['comment_policy'] = 'none'; } $r = q("SELECT * FROM item left join xchan on author_xchan = xchan_hash WHERE resource_id = '%s' AND resource_type = 'event' and uid = %d LIMIT 1", - dbesc($event['event_hash']), + dbesc($event['event_hash']), intval($arr['uid']) ); if($r) { - $obj = json_encode(array( + $object = json_encode(array( 'type' => ACTIVITY_OBJ_EVENT, 'id' => z_root() . '/event/' . $r[0]['resource_id'], 'title' => $arr['summary'], @@ -424,8 +439,7 @@ function event_store_item($arr,$event) { intval($arr['uid']) ); - - $s = q("delete from term where oid = %d and otype = %d", + q("delete from term where oid = %d and otype = %d", intval($r[0]['id']), intval(TERM_OBJ_POST) ); @@ -442,21 +456,19 @@ function event_store_item($arr,$event) { dbesc($t['url']) ); } - } + } $item_id = $r[0]['id']; call_hooks('event_updated', $event['id']); + return $item_id; - } - else { + } else { $z = q("select * from channel where channel_id = %d limit 1", intval($arr['uid']) ); - $private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0); - if($item) { $item_arr['id'] = $item['id']; @@ -469,8 +481,7 @@ function event_store_item($arr,$event) { $item_flags |= ITEM_WALL; $item_flags |= ITEM_ORIGIN; } - $item_arr['item_flags'] = $item_flags; - + $item_arr['item_flags'] = $item_flags; } if(! $arr['mid']) @@ -482,7 +493,6 @@ function event_store_item($arr,$event) { $item_arr['mid'] = $arr['mid']; $item_arr['parent_mid'] = $arr['mid']; - $item_arr['owner_xchan'] = (($wall) ? $z[0]['channel_hash'] : $arr['event_xchan']); $item_arr['author_xchan'] = $arr['event_xchan']; $item_arr['title'] = $arr['summary']; @@ -493,9 +503,8 @@ function event_store_item($arr,$event) { $item_arr['item_private'] = $private; $item_arr['verb'] = ACTIVITY_POST; - - if(array_key_exists('term',$arr)) - $item_arr['term'] = $arr['term']; + if(array_key_exists('term', $arr)) + $item_arr['term'] = $arr['term']; $item_arr['resource_type'] = 'event'; $item_arr['resource_id'] = $event['event_hash']; @@ -512,15 +521,13 @@ function event_store_item($arr,$event) { else $item_arr['plink'] = z_root() . '/display/' . $item_arr['mid']; - $x = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($arr['event_xchan']) ); if($x) { - $item_arr['object'] = json_encode(array( 'type' => ACTIVITY_OBJ_EVENT, - 'id' => z_root() . '/event/' . $hash, + 'id' => z_root() . '/event/' . $event['event_hash'], 'title' => $arr['summary'], 'content' => format_event_bbcode($arr), 'author' => array( @@ -539,7 +546,7 @@ function event_store_item($arr,$event) { $item_id = $res['item_id']; - call_hooks("event_created", $event['id']); + call_hooks('event_created', $event['id']); return $item_id; } diff --git a/include/expire.php b/include/expire.php index b244e65f5..e5d456896 100644 --- a/include/expire.php +++ b/include/expire.php @@ -1,4 +1,7 @@ -<?php /** @file */ +<?php +/** + * @file include/expire.php + */ require_once('boot.php'); require_once('include/cli_startup.php'); @@ -7,62 +10,60 @@ function expire_run($argv, $argc){ cli_startup(); - // perform final cleanup on previously delete items - $r = q("select id from item where (item_restrict & %d) > 0 and (item_restrict & %d) = 0 + $r = q("select id from item where (item_restrict & %d) > 0 and (item_restrict & %d) = 0 and changed < %s - INTERVAL %s", intval(ITEM_DELETED), intval(ITEM_PENDING_REMOVE), db_utcnow(), db_quoteinterval('10 DAY') ); - if($r) { - foreach($r as $rr) { - drop_item($rr['id'],false,DROPITEM_PHASE2); + if ($r) { + foreach ($r as $rr) { + drop_item($rr['id'], false, DROPITEM_PHASE2); } } // physically remove anything that has been deleted for more than two months - // FIXME - this is a wretchedly inefficient query + /** @FIXME - this is a wretchedly inefficient query */ $r = q("delete from item where ( item_restrict & %d ) > 0 and changed < %s - INTERVAL %s", intval(ITEM_PENDING_REMOVE), db_utcnow(), db_quoteinterval('36 DAY') ); - // make this optional as it could have a performance impact on large sites + /** @FIXME make this optional as it could have a performance impact on large sites */ - if(intval(get_config('system','optimize_items'))) + if (intval(get_config('system', 'optimize_items'))) q("optimize table item"); logger('expire: start', LOGGER_DEBUG); - + $site_expire = get_config('system', 'default_expire_days'); logger('site_expire: ' . $site_expire); $r = q("SELECT channel_id, channel_address, channel_pageflags, channel_expire_days from channel where true"); - if($r) { - foreach($r as $rr) { + if ($r) { + foreach ($r as $rr) { // expire the sys channel separately - if($rr['channel_pageflags'] & PAGE_SYSTEM) + if ($rr['channel_pageflags'] & PAGE_SYSTEM) continue; // service class default (if non-zero) over-rides the site default - $service_class_expire = service_class_fetch($rr['channel_id'],'expire_days'); - if(intval($service_class_expire)) + $service_class_expire = service_class_fetch($rr['channel_id'], 'expire_days'); + if (intval($service_class_expire)) $channel_expire = $service_class_expire; else $channel_expire = $site_expire; - if(intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) || + if (intval($channel_expire) && (intval($channel_expire) < intval($rr['channel_expire_days'])) || intval($rr['channel_expire_days'] == 0)) { $expire_days = $channel_expire; - } - else { + } else { $expire_days = $rr['channel_expire_days']; } @@ -72,34 +73,30 @@ function expire_run($argv, $argc){ } } - $x = get_sys_channel(); - if($x) { + if ($x) { // this should probably just fetch the channel_expire_days from the sys channel, // but there's no convenient way to set it. - $expire_days = get_config('system','sys_expire_days'); - if($expire_days === false) + $expire_days = get_config('system', 'sys_expire_days'); + if ($expire_days === false) $expire_days = 30; - if(intval($site_expire) && (intval($site_expire) < intval($expire_days))) { + if (intval($site_expire) && (intval($site_expire) < intval($expire_days))) { $expire_days = $site_expire; } logger('Expire: sys interval: ' . $expire_days, LOGGER_DEBUG); - if($expire_days) - item_expire($x['channel_id'],$expire_days); + if ($expire_days) + item_expire($x['channel_id'], $expire_days); logger('Expire: sys: done', LOGGER_DEBUG); - } - - return; } -if (array_search(__file__,get_included_files())===0){ - expire_run($argv,$argc); - killme(); +if (array_search(__file__, get_included_files()) === 0){ + expire_run($argv, $argc); + killme(); } diff --git a/include/identity.php b/include/identity.php index af6cb74d2..7884c04d2 100644 --- a/include/identity.php +++ b/include/identity.php @@ -1,27 +1,29 @@ -<?php /** @file */ +<?php +/** + * @file include/identity.php + */ require_once('include/zot.php'); require_once('include/crypto.php'); /** - * @function identity_check_service_class($account_id) - * Called when creating a new channel. Checks the account's service class and number - * of current channels to determine whether creating a new channel is within the current - * service class constraints. + * @brief Called when creating a new channel. + * + * Checks the account's service class and number of current channels to determine + * whether creating a new channel is within the current service class constraints. * * @param int $account_id * Account_id used for this request * - * @returns array - * 'success' => boolean true if creating a new channel is allowed for this account - * 'message' => if success is false, optional error text + * @returns assoziative array with: + * * \e boolean \b success boolean true if creating a new channel is allowed for this account + * * \e string \b message (optional) if success is false, optional error text + * * \e int \b total_identities */ - - function identity_check_service_class($account_id) { - $ret = array('success' => false, $message => ''); - + $ret = array('success' => false, 'message' => ''); + $r = q("select count(channel_id) as total from channel where channel_account_id = %d and not ( channel_pageflags & %d )>0 ", intval($account_id), intval(PAGE_REMOVED) @@ -30,68 +32,67 @@ function identity_check_service_class($account_id) { $ret['total_identities'] = 0; $ret['message'] = t('Unable to obtain identity information from database'); return $ret; - } + } $ret['total_identities'] = intval($r[0]['total']); - if(! account_service_class_allows($account_id,'total_identities',$r[0]['total'])) { - $result['message'] .= upgrade_message(); - return $result; + if (! account_service_class_allows($account_id, 'total_identities', $r[0]['total'])) { + $ret['message'] .= upgrade_message(); + return $ret; } $ret['success'] = true; + return $ret; } /** - * @function validate_channelname($name) - * Determine if the channel name is allowed when creating a new channel. + * @brief Determine if the channel name is allowed when creating a new channel. + * * This action is pluggable. + * We're currently only checking for an empty name or one that exceeds our + * storage limit (255 chars). 255 chars is probably going to create a mess on + * some pages. + * Plugins can set additional policies such as full name requirements, character + * sets, multi-byte length, etc. * * @param string $name * * @returns nil return if name is valid, or string describing the error state. - * - * We're currently only checking for an empty name or one that exceeds our storage limit (255 chars). - * 255 chars is probably going to create a mess on some pages. - * Plugins can set additional policies such as full name requirements, character sets, multi-byte - * length, etc. - * */ - function validate_channelname($name) { - if(! $name) + if (! $name) return t('Empty name'); - if(strlen($name) > 255) + + if (strlen($name) > 255) return t('Name too long'); + $arr = array('name' => $name); - call_hooks('validate_channelname',$arr); - if(x($arr,'message')) + call_hooks('validate_channelname', $arr); + + if (x($arr, 'message')) return $arr['message']; - return; } /** - * @function create_sys_channel() - * Create a system channel - which has no account attached + * @brief Create a system channel - which has no account attached. * */ - function create_sys_channel() { - if(get_sys_channel()) + if (get_sys_channel()) return; - // Ensure that there is a host keypair. + // Ensure that there is a host keypair. - if((! get_config('system','pubkey')) && (! get_config('system','prvkey'))) { + if ((! get_config('system', 'pubkey')) && (! get_config('system', 'prvkey'))) { require_once('include/crypto.php'); - $hostkey = new_keypair(4096); - set_config('system','pubkey',$hostkey['pubkey']); - set_config('system','prvkey',$hostkey['prvkey']); - } + $hostkey = new_keypair(4096); + set_config('system', 'pubkey', $hostkey['pubkey']); + set_config('system', 'prvkey', $hostkey['prvkey']); + } create_identity(array( 'account_id' => 'xxx', // This will create an identity with an (integer) account_id of 0, but account_id is required @@ -103,63 +104,79 @@ function create_sys_channel() { )); } + +/** + * @brief Returns the sys channel. + * + * @return array|boolean + */ function get_sys_channel() { $r = q("select * from channel left join xchan on channel_hash = xchan_hash where (channel_pageflags & %d)>0 limit 1", intval(PAGE_SYSTEM) ); - if($r) + + if ($r) return $r[0]; + return false; } + +/** + * @brief Checks if $channel_id is sys channel. + * + * @param int $channel_id + * @return boolean + */ function is_sys_channel($channel_id) { $r = q("select channel_pageflags from channel where channel_id = %d limit 1", intval($channel_id) ); - if(($r) && ($r[0]['channel_pageflags'] & PAGE_SYSTEM)) + + if (($r) && ($r[0]['channel_pageflags'] & PAGE_SYSTEM)) return true; + return false; } /** - * @channel_total() - * Return the total number of channels on this site. No filtering is performed except to check PAGE_REMOVED + * @brief Return the total number of channels on this site. * - * @returns int - * on error returns boolean false + * No filtering is performed except to check PAGE_REMOVED. * + * @returns int|booleean + * on error returns boolean false */ - function channel_total() { $r = q("select channel_id from channel where not ( channel_pageflags & %d )>0", intval(PAGE_REMOVED) ); - if(is_array($r)) + if (is_array($r)) return count($r); + return false; } /** - * @function create_identity($arr) - * Create a new channel - * Also creates the related xchan, hubloc, profile, and "self" abook records, and an - * empty "Friends" group/collection for the new channel + * @brief Create a new channel. + * + * Also creates the related xchan, hubloc, profile, and "self" abook records, + * and an empty "Friends" group/collection for the new channel. * - * @param array $arr - * 'name' => full name of channel - * 'nickname' => "email/url-compliant" nickname - * 'account_id' => account_id to attach with this channel - * [other identity fields as desired] + * @param array $arr assoziative array with: + * * \e string \b name full name of channel + * * \e string \b nickname "email/url-compliant" nickname + * * \e int \b account_id to attach with this channel + * * [other identity fields as desired] * * @returns array * 'success' => boolean true or false * 'message' => optional error text if success is false * 'channel' => if successful the created channel array */ - function create_identity($arr) { $a = get_app(); @@ -176,7 +193,6 @@ function create_identity($arr) { // save this for auto_friending $total_identities = $ret['total_identities']; - $nick = mb_strtolower(trim($arr['nickname'])); if(! $nick) { $ret['message'] = t('Nickname is required.'); @@ -205,7 +221,6 @@ function create_identity($arr) { $guid = zot_new_uid($nick); $key = new_keypair(4096); - $sig = base64url_encode(rsa_sign($guid,$key['prvkey'])); $hash = make_xchan_hash($guid,$sig); @@ -221,9 +236,6 @@ function create_identity($arr) { if(array_key_exists('primary', $arr)) $primary = intval($arr['primary']); - - $perms_sql = ''; - $role_permissions = null; $global_perms = get_perms(); @@ -269,7 +281,6 @@ function create_identity($arr) { intval($expire), dbesc($a->timezone) ); - $r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1", @@ -281,7 +292,7 @@ function create_identity($arr) { $ret['message'] = t('Unable to retrieve created identity'); return $ret; } - + $ret['channel'] = $r[0]; if(intval($arr['account_id'])) @@ -307,7 +318,6 @@ function create_identity($arr) { if(! $r) logger('create_identity: Unable to store hub location'); - $newuid = $ret['channel']['channel_id']; $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_l, xchan_photo_m, xchan_photo_s, xchan_addr, xchan_url, xchan_follow, xchan_connurl, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags ) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)", @@ -329,9 +339,8 @@ function create_identity($arr) { intval($xchanflags) ); - // Not checking return value. + // Not checking return value. // It's ok for this to fail if it's an imported channel, and therefore the hash is a duplicate - $r = q("INSERT INTO profile ( aid, uid, profile_guid, profile_name, is_default, publish, name, photo, thumb) VALUES ( %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s') ", @@ -418,37 +427,31 @@ function create_identity($arr) { } call_hooks('register_account', $newuid); - + proc_run('php','include/directory.php', $ret['channel']['channel_id']); } $ret['success'] = true; return $ret; - } - /** - * @function set_default_login_identity($account_id, $channel_id, $force = true) - * Set default channel to be used on login + * @brief Set default channel to be used on login. * * @param int $account_id * login account * @param int $channel_id * channel id to set as default for this account - * @param boolean force + * @param boolean $force * if true, set this default unconditionally * if $force is false only do this if there is no existing default - * - * @returns nil */ - -function set_default_login_identity($account_id,$channel_id,$force = true) { +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", intval($account_id) ); - if($r) { - if((intval($r[0]['account_default_channel']) == 0) || ($force)) { + if ($r) { + if ((intval($r[0]['account_default_channel']) == 0) || ($force)) { $r = q("update account set account_default_channel = %d where account_id = %d", intval($channel_id), intval($account_id) @@ -458,8 +461,7 @@ function set_default_login_identity($account_id,$channel_id,$force = true) { } /** - * @function identity_basic_export($channel_id,$items = false) - * Create an array representing the important channel information + * @brief Create an array representing the important channel information * which would be necessary to create a nomadic identity clone. This includes * most channel resources and connection information with the exception of content. * @@ -470,9 +472,7 @@ function set_default_login_identity($account_id,$channel_id,$force = true) { * * @returns array * See function for details - * */ - function identity_basic_export($channel_id, $items = false) { /* @@ -536,7 +536,6 @@ function identity_basic_export($channel_id, $items = false) { if($r) $ret['config'] = $r; - $r = q("select type, data from photo where scale = 4 and profile = 1 and uid = %d limit 1", intval($channel_id) ); @@ -563,11 +562,9 @@ function identity_basic_export($channel_id, $items = false) { if($r) $ret['obj'] = $r; - if(! $items) return $ret; - $r = q("select likes.*, item.mid from likes left join item on likes.iid = item.id where likes.channel_id = %d", intval($channel_id) ); @@ -575,17 +572,16 @@ function identity_basic_export($channel_id, $items = false) { if($r) $ret['likes'] = $r; - $r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d", intval($channel_id) ); - + if($r) - $ret['item_id'] = $r; + $ret['item_id'] = $r; - $key = get_config('system','prvkey'); + //$key = get_config('system','prvkey'); - // warning: this may run into memory limits on smaller systems + /** @warning this may run into memory limits on smaller systems */ $r = q("select * from item where (item_flags & %d)>0 and not (item_restrict & %d)>0 and uid = %d", intval(ITEM_WALL), @@ -598,25 +594,17 @@ function identity_basic_export($channel_id, $items = false) { $r = fetch_post_tags($r,true); foreach($r as $rr) $ret['item'][] = encode_item($rr,true); - } - return $ret; + return $ret; } - /** + * @brief Loads a profile into the App structure. * - * @function : profile_load(&$a, $nickname, $profile) - * Generate - * @param App $a - * @param string $nickname - * @param string $profile - * - * Summary: Loads a profile into the App structure. - * The function requires a writeable copy of the main App structure, and the nickname - * of a valid channel. + * The function requires a writeable copy of the main App structure, and the + * nickname of a valid channel. * * Permissions of the current observer are checked. If a restricted profile is available * to the current observer, that will be loaded instead of the channel default profile. @@ -625,9 +613,10 @@ function identity_basic_export($channel_id, $items = false) { * * The channel default theme is also selected for use, unless over-riden elsewhere. * + * @param[in,out] App &$a + * @param string $nickname + * @param string $profile */ - - function profile_load(&$a, $nickname, $profile = '') { logger('profile_load: ' . $nickname . (($profile) ? ' profile: ' . $profile : '')); @@ -635,7 +624,7 @@ function profile_load(&$a, $nickname, $profile = '') { $user = q("select channel_id from channel where channel_address = '%s' limit 1", dbesc($nickname) ); - + if(! $user) { logger('profile error: ' . $a->query_string, LOGGER_DEBUG); notice( t('Requested channel is not available.') . EOL ); @@ -683,7 +672,6 @@ function profile_load(&$a, $nickname, $profile = '') { ); } - if(! $p) { logger('profile error: ' . $a->query_string, LOGGER_DEBUG); notice( t('Requested profile is not available.') . EOL ); @@ -729,10 +717,11 @@ function profile_load(&$a, $nickname, $profile = '') { $p[0]['picdate'] = $z[0]['xchan_photo_date']; $p[0]['reddress'] = str_replace('@','@',$z[0]['xchan_addr']); } - + // fetch user tags if this isn't the default profile if(! $p[0]['is_default']) { + /** @BUG $profile_uid is undefinded for this query, so should not work. */ $x = q("select `keywords` from `profile` where uid = %d and `is_default` = 1 limit 1", intval($profile_uid) ); @@ -744,7 +733,6 @@ function profile_load(&$a, $nickname, $profile = '') { $keywords = str_replace(array('#',',',' ',',,'),array('',' ',',',','),$p[0]['keywords']); if(strlen($keywords) && $can_view_profile) $a->page['htmlhead'] .= '<meta name="keywords" content="' . htmlentities($keywords,ENT_COMPAT,'UTF-8') . '" />' . "\r\n" ; - } $a->profile = $p[0]; @@ -756,7 +744,6 @@ function profile_load(&$a, $nickname, $profile = '') { if($can_view_profile) { $online = get_online_status($nickname); $a->profile['online_status'] = $online['result']; - } if(local_channel()) { @@ -764,7 +751,7 @@ function profile_load(&$a, $nickname, $profile = '') { $_SESSION['mobile_theme'] = $a->profile['channel_mobile_theme']; } - /** + /* * load/reload current theme info */ @@ -776,36 +763,34 @@ function profile_load(&$a, $nickname, $profile = '') { // if (file_exists($theme_info_file)){ // require_once($theme_info_file); // } - - return; } -function profile_create_sidebar(&$a,$connect = true) { +/** + * @brief + * + * @param App &$a + * @param boolean $connect + */ +function profile_create_sidebar(&$a, $connect = true) { - $block = (((get_config('system','block_public')) && (! local_channel()) && (! remote_channel())) ? true : false); + $block = (((get_config('system', 'block_public')) && (! local_channel()) && (! remote_channel())) ? true : false); - $a->set_widget('profile',profile_sidebar($a->profile, $block, $connect)); - return; + $a->set_widget('profile', profile_sidebar($a->profile, $block, $connect)); } - /** + * @brief Formats a profile for display in the sidebar. * - * Function: profile_sidebar - * - * Formats a profile for display in the sidebar. * It is very difficult to templatise the HTML completely * because of all the conditional logic. * - * @parameter: array $profile + * @param array $profile + * @param int $block + * @param boolean $show_connect * - * Returns HTML string stuitable for sidebar inclusion + * @return HTML string suitable for sidebar inclusion * Exceptions: Returns empty string if passed $profile is wrong type or not populated - * */ - - - function profile_sidebar($profile, $block = 0, $show_connect = true) { $a = get_app(); @@ -814,14 +799,12 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { $o = ''; $location = false; - $address = false; $pdesc = true; $reddress = true; if((! is_array($profile)) && (! count($profile))) return $o; - head_set_icon($profile['thumb']); $is_owner = (($profile['uid'] == local_channel()) ? true : false); @@ -849,13 +832,11 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { // show edit profile to yourself if($is_owner) { - $profile['menu'] = array( 'chg_photo' => t('Change profile photo'), 'entries' => array(), ); - $multi_profiles = feature_enabled(local_channel(), 'multi_profiles'); if($multi_profiles) { $profile['edit'] = array($a->get_baseurl(). '/profiles', t('Profiles'),"", t('Manage/edit profiles')); @@ -863,10 +844,9 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { } else $profile['edit'] = array($a->get_baseurl() . '/profiles/' . $profile['id'], t('Edit Profile'),'',t('Edit Profile')); - + $r = q("SELECT * FROM `profile` WHERE `uid` = %d", local_channel()); - if($r) { foreach($r as $rr) { @@ -899,21 +879,21 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) { $marital = ((x($profile,'marital') == 1) ? t('Status:') : False); $homepage = ((x($profile,'homepage') == 1) ? t('Homepage:') : False); $profile['online'] = (($profile['online_status'] === 'online') ? t('Online Now') : False); -logger('online: ' . $profile['online']); + logger('online: ' . $profile['online']); if(! perm_is_allowed($profile['uid'],((is_array($observer)) ? $observer['xchan_hash'] : ''),'view_profile')) { $block = true; } if(($profile['hidewall'] && (! local_channel()) && (! remote_channel())) || $block ) { - $location = $reddress = $pdesc = $gender = $marital = $homepage = $online = False; + $location = $reddress = $pdesc = $gender = $marital = $homepage = False; } $firstname = ((strpos($profile['channel_name'],' ')) ? trim(substr($profile['channel_name'],0,strpos($profile['channel_name'],' '))) : $profile['channel_name']); $lastname = (($firstname === $profile['channel_name']) ? '' : trim(substr($profile['channel_name'],strlen($firstname)))); - $diaspora = array( + $diaspora = array( 'podloc' => z_root(), 'searchable' => (($block) ? 'false' : 'true'), 'nickname' => $profile['channel_address'], @@ -970,9 +950,9 @@ logger('online: ' . $profile['online']); } -// FIXME or remove - - +/** + * @FIXME or remove + */ function get_birthdays() { $a = get_app(); @@ -1030,7 +1010,6 @@ logger('online: ' . $profile['online']); $rr['date'] = day_translate(datetime_convert('UTC', $a->timezone, $rr['start'], $rr['adjust'] ? $bd_format : $bd_short)) . (($today) ? ' ' . t('[today]') : ''); $rr['startime'] = Null; $rr['today'] = $today; - } } } @@ -1044,14 +1023,13 @@ logger('online: ' . $profile['online']); '$events' => $r, '$lbr' => '{', // raw brackets mess up if/endif macro processing '$rbr' => '}' - )); } -// FIXME - - +/** + * @FIXME + */ function get_events() { require_once('include/bbcode.php'); @@ -1085,7 +1063,6 @@ logger('online: ' . $profile['online']); } $classtoday = (($istoday) ? 'event-today' : ''); - foreach($r as &$rr) { if($rr['adjust']) $md = datetime_convert('UTC',$a->timezone,$rr['start'],'Y/m'); @@ -1132,19 +1109,19 @@ function advanced_profile(&$a) { if($a->profile['name']) { $tpl = get_markup_template('profile_advanced.tpl'); - + $profile = array(); - + $profile['fullname'] = array( t('Full Name:'), $a->profile['name'] ) ; - + if($a->profile['gender']) $profile['gender'] = array( t('Gender:'), $a->profile['gender'] ); - + $ob_hash = get_observer_hash(); if($ob_hash && perm_is_allowed($a->profile['profile_uid'],$ob_hash,'post_like')) { $profile['canlike'] = true; $profile['likethis'] = t('Like this channel'); $profile['profile_guid'] = $a->profile['profile_guid']; - } + } $likers = q("select liker, xchan.* from likes left join xchan on liker = xchan_hash where channel_id = %d and target_type = '%s' and verb = '%s'", intval($a->profile['profile_uid']), @@ -1175,19 +1152,19 @@ function advanced_profile(&$a) { : day_translate(datetime_convert('UTC','UTC','2001-' . substr($a->profile['dob'],5) . ' 00:00 +00:00',$short_bd_format))); } $profile['birthday'] = array( t('Birthday:'), $val); - } - if($age = age($a->profile['dob'],$a->profile['timezone'],'')) $profile['age'] = array( t('Age:'), $age ); - - - if($a->profile['marital']) $profile['marital'] = array( t('Status:'), $a->profile['marital']); + if($age = age($a->profile['dob'],$a->profile['timezone'],'')) + $profile['age'] = array( t('Age:'), $age ); + if($a->profile['marital']) + $profile['marital'] = array( t('Status:'), $a->profile['marital']); - if($a->profile['with']) $profile['marital']['with'] = bbcode($a->profile['with']); + if($a->profile['with']) + $profile['marital']['with'] = bbcode($a->profile['with']); if(strlen($a->profile['howlong']) && $a->profile['howlong'] !== NULL_DATE) { - $profile['howlong'] = relative_date($a->profile['howlong'], t('for %1$d %2$s')); + $profile['howlong'] = relative_date($a->profile['howlong'], t('for %1$d %2$s')); } if($a->profile['sexual']) $profile['sexual'] = array( t('Sexual Preference:'), $a->profile['sexual'] ); @@ -1243,54 +1220,55 @@ function advanced_profile(&$a) { // logger('mod_profile: things: ' . print_r($things,true), LOGGER_DATA); - return replace_macros($tpl, array( - '$title' => t('Profile'), + return replace_macros($tpl, array( + '$title' => t('Profile'), '$canlike' => (($profile['canlike'])? true : false), '$likethis' => t('Like this thing'), - '$profile' => $profile, + '$profile' => $profile, '$things' => $things - )); - } + )); + } return ''; } - - function get_my_url() { - if(x($_SESSION,'zrl_override')) + if(x($_SESSION, 'zrl_override')) return $_SESSION['zrl_override']; - if(x($_SESSION,'my_url')) + if(x($_SESSION, 'my_url')) return $_SESSION['my_url']; + return false; } function get_my_address() { - if(x($_SESSION,'zid_override')) + if(x($_SESSION, 'zid_override')) return $_SESSION['zid_override']; - if(x($_SESSION,'my_address')) + if(x($_SESSION, 'my_address')) return $_SESSION['my_address']; + return false; } /** - * @function zid_init(&$a) - * 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. + * @brief + * + * 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. + * + * @param App &$a * * @hooks 'zid_init' * string 'zid' - their zid * string 'url' - the destination url - * */ - function zid_init(&$a) { $tmp_str = get_my_address(); if(validate_email($tmp_str)) { proc_run('php','include/gprobe.php',bin2hex($tmp_str)); $arr = array('zid' => $tmp_str, 'url' => $a->cmd); - call_hooks('zid_init',$arr); + 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) @@ -1312,8 +1290,8 @@ function zid_init(&$a) { } /** - * @function zid($s,$address = '') - * Adds a zid parameter to a url + * @brief Adds a zid parameter to a url. + * * @param string $s * The url to accept the zid * @param boolean $address @@ -1325,31 +1303,33 @@ function zid_init(&$a) { * string zid - urlencoded zid * string result - the return string we calculated, change it if you want to return something else */ - - function zid($s,$address = '') { - if(! strlen($s) || strpos($s,'zid=')) + if (! strlen($s) || strpos($s,'zid=')) return $s; + $has_params = ((strpos($s,'?')) ? true : false); - $num_slashes = substr_count($s,'/'); - if(! $has_params) - $has_params = ((strpos($s,'&')) ? true : false); + $num_slashes = substr_count($s, '/'); + if (! $has_params) + $has_params = ((strpos($s, '&')) ? true : false); + $achar = strpos($s,'?') ? '&' : '?'; $mine = get_my_url(); $myaddr = (($address) ? $address : get_my_address()); - // FIXME checking against our own channel url is no longer reliable. We may have a lot - // of urls attached to out channel. Should probably match against our site, since we - // will not need to remote authenticate on our own site anyway. + /** @FIXME checking against our own channel url is no longer reliable. We may have a lot + * of urls attached to out channel. Should probably match against our site, since we + * will not need to remote authenticate on our own site anyway. + */ - if($mine && $myaddr && (! link_compare($mine,$s))) + if ($mine && $myaddr && (! link_compare($mine,$s))) $zurl = $s . (($num_slashes >= 3) ? '' : '/') . $achar . 'zid=' . urlencode($myaddr); else $zurl = $s; $arr = array('url' => $s, 'zid' => urlencode($myaddr), 'result' => $zurl); call_hooks('zid', $arr); + return $arr['result']; } @@ -1369,55 +1349,45 @@ function get_theme_uid() { $x = get_sys_channel(); if($x) return $x['channel_id']; - } + } + return $uid; } /** -* @function get_default_profile_photo($size = 175) -* Retrieves the path of the default_profile_photo for this system -* with the specified size. +* @brief Retrieves the path of the default_profile_photo for this system +* with the specified size. +* * @param int $size -* one of (175, 80, 48) +* one of (175, 80, 48) * @returns string -* */ - function get_default_profile_photo($size = 175) { - $scheme = get_config('system','default_profile_photo'); - if(! $scheme) - $scheme = 'rainbow_man'; - return 'images/default_profile_photos/' . $scheme . '/' . $size . '.png'; -} + $scheme = get_config('system','default_profile_photo'); + if(! $scheme) + $scheme = 'rainbow_man'; + return 'images/default_profile_photos/' . $scheme . '/' . $size . '.png'; +} /** + * @brief Test whether a given identity is NOT a member of the Red Matrix. * - * @function is_foreigner($s) - * Test whether a given identity is NOT a member of the Red Matrix * @param string $s; * xchan_hash of the identity in question - * * @returns boolean true or false - * */ - function is_foreigner($s) { - return((strpbrk($s,'.:@')) ? true : false); + return((strpbrk($s, '.:@')) ? true : false); } - /** + * @brief Test whether a given identity is a member of the Red Matrix. * - * @function is_member($s) - * Test whether a given identity is a member of the Red Matrix * @param string $s; * xchan_hash of the identity in question - * * @returns boolean true or false - * */ - function is_member($s) { return((is_foreigner($s)) ? false : true); } @@ -1464,8 +1434,8 @@ function remote_online_status($webbie) { if($j) $result = (($j['result']) ? $j['result'] : false); } - return $result; + return $result; } @@ -1477,17 +1447,20 @@ function get_channel_by_nick($nick) { } - +/** + * @brief + * + * @return string + */ function identity_selector() { - if(local_channel()) { + 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_pageflags & %d) = 0 order by channel_name ", intval(get_account_id()), intval(PAGE_REMOVED) ); - if(count($r) > 1) { - $selected_channel = null; - $account = get_app()->get_account(); - $o = replace_macros(get_markup_template('channel_id_select.tpl'),array( + if (count($r) > 1) { + //$account = get_app()->get_account(); + $o = replace_macros(get_markup_template('channel_id_select.tpl'), array( '$channels' => $r, '$selected' => local_channel() )); @@ -1507,6 +1480,7 @@ function is_public_profile() { $channel = get_app()->get_channel(); if($channel && $channel['channel_r_profile'] == PERMS_PUBLIC) return true; + return false; } @@ -1522,7 +1496,6 @@ function get_profile_fields_basic($filter = 0) { $x[$f] = 1; return $x; - } @@ -1536,6 +1509,7 @@ function get_profile_fields_advanced($filter = 0) { if($basic) foreach($basic as $f => $v) $x[$f] = $v; + if($profile_fields_advanced) foreach($profile_fields_advanced as $f) $x[$f] = 1; @@ -1544,28 +1518,26 @@ function get_profile_fields_advanced($filter = 0) { } /** - * @function notifications_off($channel_id) - * Clear notifyflags for a channel - most likely during bulk import of content or other activity that is likely - * to generate huge amounts of undesired notifications. + * @brief Clear notifyflags for a channel. + * + * Most likely during bulk import of content or other activity that is likely + * to generate huge amounts of undesired notifications. + * * @param int $channel_id * The channel to disable notifications for * @returns int * Current notification flag value. Send this to notifications_on() to restore the channel settings when finished * with the activity requiring notifications_off(); */ - - - function notifications_off($channel_id) { $r = q("select channel_notifyflags from channel where channel_id = %d limit 1", intval($channel_id) ); - $x = q("update channel set channel_notifyflags = 0 where channel_id = %d", + q("update channel set channel_notifyflags = 0 where channel_id = %d", intval($channel_id) ); return intval($r[0]['channel_notifyflags']); - } @@ -1586,5 +1558,6 @@ function get_channel_default_perms($uid) { ); if($r) return $r[0]['abook_my_perms']; + return 0; } diff --git a/include/items.php b/include/items.php index ef269b9c4..4b83ce3e3 100755 --- a/include/items.php +++ b/include/items.php @@ -1,4 +1,7 @@ -<?php /** @file */ +<?php +/** + * @file include/items.php + */ require_once('include/bbcode.php'); require_once('include/oembed.php'); @@ -6,8 +9,14 @@ require_once('include/crypto.php'); require_once('include/photo/photo_driver.php'); require_once('include/permissions.php'); - -function collect_recipients($item,&$private_envelope) { +/** + * @brief Collects recipients. + * + * @param array $item + * @param[out] boolean $private_envelope + * @return array containing the recipients + */ +function collect_recipients($item, &$private_envelope) { require_once('include/group.php'); @@ -67,7 +76,7 @@ function collect_recipients($item,&$private_envelope) { $private_envelope = false; require_once('include/identity.php'); - $sys = get_sys_channel(); + //$sys = get_sys_channel(); if(array_key_exists('public_policy',$item) && $item['public_policy'] !== 'self') { $r = q("select abook_xchan, xchan_network from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and not (abook_flags & %d)>0 ", @@ -84,7 +93,7 @@ function collect_recipients($item,&$private_envelope) { switch($policy) { case 'net': case 'aut': - case 'sit': + case 'sit': case 'any': case 'con': if($rr['xchan_network'] != 'zot') @@ -103,7 +112,6 @@ function collect_recipients($item,&$private_envelope) { } } - // This is a somewhat expensive operation but important. // Don't send this item to anybody who isn't allowed to see it @@ -129,7 +137,6 @@ function collect_recipients($item,&$private_envelope) { $recipients[] = $item['owner_xchan']; return $recipients; - } /** @@ -139,30 +146,35 @@ function collect_recipients($item,&$private_envelope) { * They can still be addressed individually. * Networks may need to be added or removed from this list as circumstances change. * - * Update: this may need to be the default, which will force people to opt-in to sending stuff - * privately to insecure platforms. + * Update: this may need to be the default, which will force people to opt-in to + * sending stuff privately to insecure platforms. + * + * @param int $channel_id + * @param array $arr + * @return array containing the sane xchan_hashes */ - -function filter_insecure($channel_id,$arr) { +function filter_insecure($channel_id, $arr) { $insecure_nets = " and not xchan_network in ('diaspora', 'friendica-over-diaspora') "; $ret = array(); - if((! intval(get_config($channel_id,'system','filter_insecure_collections'))) || (! $arr)) + if((! intval(get_config($channel_id, 'system', 'filter_insecure_collections'))) || (! $arr)) return $arr; $str = ''; foreach($arr as $rr) { if(strlen($str)) $str .= ','; + $str .= "'" . dbesc($rr) . "'"; } - $r = q("select xchan_hash from xchan where xchan_hash in ($str) $insecure_nets "); + $r = q("select xchan_hash from xchan where xchan_hash in ($str) $insecure_nets"); if($r) { foreach($r as $rr) { $ret[] = $rr['xchan_hash']; } } + return $ret; } @@ -173,12 +185,13 @@ function comments_are_now_closed($item) { if($d > $item['comments_closed']) return true; } + return false; } /** - * @function can_comment_on_post($observer_xchan,$item); + * @brief * * This function examines the comment_policy attached to an item and decides if the current observer has * sufficient privileges to comment. This will normally be called on a remote site where perm_is_allowed() @@ -187,16 +200,18 @@ function comments_are_now_closed($item) { * If it is, you should be able to use perm_is_allowed( ... 'post_comments'), and if it isn't you need to call * can_comment_on_post() * We also check the comments_closed date/time on the item if this is set. + * + * @param string $observer_xchan + * @param array $item + * @return boolean */ - -function can_comment_on_post($observer_xchan,$item) { +function can_comment_on_post($observer_xchan, $item) { // logger('can_comment_on_post: comment_policy: ' . $item['comment_policy'], LOGGER_DEBUG); if(! $observer_xchan) return false; - if($item['comment_policy'] === 'none') return false; @@ -205,6 +220,7 @@ function can_comment_on_post($observer_xchan,$item) { if($observer_xchan === $item['author_xchan'] || $observer_xchan === $item['owner_xchan']) return true; + switch($item['comment_policy']) { case 'self': if($observer_xchan === $item['author_xchan'] || $observer_xchan === $item['owner_xchan']) @@ -233,36 +249,36 @@ function can_comment_on_post($observer_xchan,$item) { return true; if(strstr($item['comment_policy'],'site:') && strstr($item['comment_policy'],get_app()->get_hostname())) return true; - + return false; } /** - * @function add_source_route($iid,$hash) - * Adds $hash to the item source route specified by $iid - * @param integer $iid - * item['id'] of target item - * @param string $hash - * xchan_hash of the channel that sent the item - * Modifies item pointed to by $iid + * @brief Adds $hash to the item source route specified by $iid. * * $item['route'] contains a comma-separated list of xchans that sent the current message, * somewhat analogous to the * Received: header line in email. We can use this to perform * loop detection and to avoid sending a particular item to any "upstream" sender (they - * already have a copy because they sent it to us). + * already have a copy because they sent it to us). + * + * Modifies item in the database pointed to by $iid. * + * @param integer $iid + * item['id'] of target item + * @param string $hash + * xchan_hash of the channel that sent the item */ - -function add_source_route($iid,$hash) { +function add_source_route($iid, $hash) { // logger('add_source_route ' . $iid . ' ' . $hash, LOGGER_DEBUG); if((! $iid) || (! $hash)) return; + $r = q("select route from item where id = %d limit 1", intval($iid) ); if($r) { - $new_route = (($r[0]['route']) ? $r[0]['route'] . ',' : '') . $hash; + $new_route = (($r[0]['route']) ? $r[0]['route'] . ',' : '') . $hash; q("update item set route = '%s' where id = %d", (dbesc($new_route)), intval($iid) @@ -271,17 +287,17 @@ function add_source_route($iid,$hash) { } - /** - * @function red_zrl_callback - * preg_match function when fixing 'naked' links in mod item.php - * Check if we've got a hubloc for the site and use a zrl if we do, a url if we don't. - * Remove any existing zid= param which may have been pasted by mistake - and will have - * the author's credentials. zid's are dynamic and can't really be passed around like - * that. + * @brief preg_match function when fixing 'naked' links in mod item.php. + * + * Check if we've got a hubloc for the site and use a zrl if we do, a url if we don't. + * Remove any existing zid= param which may have been pasted by mistake - and will have + * the author's credentials. zid's are dynamic and can't really be passed around like + * that. + * + * @param array $matches + * @return string */ - - function red_zrl_callback($matches) { require_once('include/hubloc.php'); $zrl = is_matrix_url($matches[2]); @@ -296,19 +312,24 @@ function red_zrl_callback($matches) { $matches[1] = ''; if($zrl) return $matches[1] . '#^[zrl=' . $matches[2] . ']' . $matches[2] . '[/zrl]'; + return $matches[1] . '#^[url=' . $matches[2] . ']' . $matches[2] . '[/url]'; } - -// If we've got a url or zrl tag with a naked url somewhere in the link text, -// escape it with quotes unless the naked url is a linked photo. - +/** + * If we've got a url or zrl tag with a naked url somewhere in the link text, + * escape it with quotes unless the naked url is a linked photo. + * + * @param array $matches + * @return string + */ function red_escape_zrl_callback($matches) { // Uncertain why the url/zrl forms weren't picked up by the non-greedy regex. - if((strpos($matches[3],'zmg') !== false) || (strpos($matches[3],'img') !== false) || (strpos($matches[3],'zrl') !== false) || (strpos($matches[3],'url') !== false)) + if((strpos($matches[3], 'zmg') !== false) || (strpos($matches[3], 'img') !== false) || (strpos($matches[3],'zrl') !== false) || (strpos($matches[3],'url') !== false)) return $matches[0]; + return '[' . $matches[1] . 'rl' . $matches[2] . ']' . $matches[3] . '"' . $matches[4] . '"' . $matches[5] . '[/' . $matches[6] . 'rl]'; } @@ -318,7 +339,6 @@ function red_escape_codeblock($m) { function red_unescape_codeblock($m) { return '[' . $m[2] . base64_decode($m[1]) . '[/' . $m[2] . ']'; - } @@ -334,28 +354,23 @@ function red_zrlify_img_callback($matches) { if($zrl) return '[zmg' . $matches[1] . ']' . $matches[2] . '[/zmg]'; + return $matches[0]; } - - /** - * @function post_activity_item($arr) - * - * post an activity - * - * @param array $arr + * @brief Post an activity. * * In its simplest form one needs only to set $arr['body'] to post a note to the logged in channel's wall. * Much more complex activities can be created. Permissions are checked. No filtering, tag expansion * or other processing is performed. * - * @returns array - * 'success' => true or false - * 'activity' => the resulting activity if successful + * @param array $arr + * @returns array + * * \e boolean \b success true or false + * * \e array \b activity the resulting activity if successful */ - function post_activity_item($arr) { $ret = array('success' => false); @@ -369,14 +384,13 @@ function post_activity_item($arr) { $arr['item_flags'] = ITEM_ORIGIN; else $arr['item_flags'] = ITEM_ORIGIN | ITEM_WALL | ITEM_THREAD_TOP; - } - + } $channel = get_app()->get_channel(); $observer = get_app()->get_observer(); - $arr['aid'] = ((x($arr,'aid')) ? $arr['aid'] : $channel['channel_account_id']); - $arr['uid'] = ((x($arr,'uid')) ? $arr['uid'] : $channel['channel_id']); + $arr['aid'] = ((x($arr,'aid')) ? $arr['aid'] : $channel['channel_account_id']); + $arr['uid'] = ((x($arr,'uid')) ? $arr['uid'] : $channel['channel_id']); if(! perm_is_allowed($arr['uid'],$observer['xchan_hash'],(($is_comment) ? 'post_comments' : 'post_wall'))) { $ret['message'] = t('Permission denied'); @@ -410,19 +424,18 @@ function post_activity_item($arr) { $arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key)); } - $arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : item_message_id()); - $arr['parent_mid'] = ((x($arr,'parent_mid')) ? $arr['parent_mid'] : $arr['mid']); - $arr['thr_parent'] = ((x($arr,'thr_parent')) ? $arr['thr_parent'] : $arr['mid']); + $arr['mid'] = ((x($arr,'mid')) ? $arr['mid'] : item_message_id()); + $arr['parent_mid'] = ((x($arr,'parent_mid')) ? $arr['parent_mid'] : $arr['mid']); + $arr['thr_parent'] = ((x($arr,'thr_parent')) ? $arr['thr_parent'] : $arr['mid']); - $arr['owner_xchan'] = ((x($arr,'owner_xchan')) ? $arr['owner_xchan'] : $channel['channel_hash']); - $arr['author_xchan'] = ((x($arr,'author_xchan')) ? $arr['author_xchan'] : $observer['xchan_hash']); + $arr['owner_xchan'] = ((x($arr,'owner_xchan')) ? $arr['owner_xchan'] : $channel['channel_hash']); + $arr['author_xchan'] = ((x($arr,'author_xchan')) ? $arr['author_xchan'] : $observer['xchan_hash']); - $arr['verb'] = ((x($arr,'verb')) ? $arr['verb'] : ACTIVITY_POST); - $arr['obj_type'] = ((x($arr,'obj_type')) ? $arr['obj_type'] : ACTIVITY_OBJ_NOTE); + $arr['verb'] = ((x($arr,'verb')) ? $arr['verb'] : ACTIVITY_POST); + $arr['obj_type'] = ((x($arr,'obj_type')) ? $arr['obj_type'] : ACTIVITY_OBJ_NOTE); if($is_comment) $arr['obj_type'] = ACTIVITY_OBJ_COMMENT; - $arr['allow_cid'] = ((x($arr,'allow_cid')) ? $arr['allow_cid'] : $channel['channel_allow_cid']); $arr['allow_gid'] = ((x($arr,'allow_gid')) ? $arr['allow_gid'] : $channel['channel_allow_gid']); $arr['deny_cid'] = ((x($arr,'deny_cid')) ? $arr['deny_cid'] : $channel['channel_deny_cid']); @@ -430,7 +443,6 @@ function post_activity_item($arr) { $arr['comment_policy'] = map_scope($channel['channel_w_comment']); - if ((! $arr['plink']) && ($arr['item_flags'] & ITEM_THREAD_TOP)) { $arr['plink'] = z_root() . '/channel/' . $channel['channel_address'] . '/?f=&mid=' . $arr['mid']; } @@ -447,7 +459,6 @@ function post_activity_item($arr) { return $ret; } - $post = item_store($arr); if($post['success']) $post_id = $post['item_id']; @@ -465,15 +476,15 @@ function post_activity_item($arr) { } return $ret; - } /** - * @function get_public_feed($channel,$params) - * generate an Atom feed + * @brief Generate an Atom feed. + * + * @param array $channel + * @param array $params */ - -function get_public_feed($channel,$params) { +function get_public_feed($channel, $params) { $type = 'xml'; $begin = NULL_DATE; @@ -494,7 +505,7 @@ function get_public_feed($channel,$params) { $params['direction'] = ((x($params,'direction')) ? $params['direction'] : 'desc'); $params['pages'] = ((x($params,'pages')) ? intval($params['pages']) : 0); $params['top'] = ((x($params,'top')) ? intval($params['top']) : 0); - + switch($params['type']) { case 'json': header("Content-type: application/atom+json"); @@ -505,24 +516,26 @@ function get_public_feed($channel,$params) { break; } - - return get_feed_for($channel,get_observer_hash(),$params); + return get_feed_for($channel, get_observer_hash(), $params); } - - - +/** + * @brief + * + * @param array $channel + * @param string $observer_hash + * @param array $params + * @return string + */ function get_feed_for($channel, $observer_hash, $params) { if(! channel) http_status_exit(401); - if($params['pages']) { if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_pages')) http_status_exit(403); - } - else { + } else { if(! perm_is_allowed($channel['channel_id'],$observer_hash,'view_stream')) http_status_exit(403); } @@ -538,7 +551,6 @@ function get_feed_for($channel, $observer_hash, $params) { 'top' => $params['top'] ), $channel, $observer_hash, CLIENT_MODE_NORMAL, get_app()->module); - $feed_template = get_markup_template('atom_feed.tpl'); $atom = ''; @@ -571,7 +583,8 @@ function get_feed_for($channel, $observer_hash, $params) { if($item['item_private']) continue; - $atom .= atom_entry($item,$type,null,$owner,true); + /** @BUG $owner is undefined in this call */ + $atom .= atom_entry($item, $type, null, $owner, true); } } @@ -604,11 +617,11 @@ function construct_activity_object($item) { if($r->title) $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n"; if($r->links) { - // FIXME!! + /** @FIXME!! */ if(substr($r->link,0,1) === '<') { $r->link = preg_replace('/\<link(.*?)\"\>/','<link$1"/>',$r->link); $o .= $r->link; - } + } else $o .= '<link rel="alternate" type="text/html" href="' . xmlify($r->link) . '" />' . "\r\n"; } @@ -635,7 +648,7 @@ function construct_activity_target($item) { if($r->title) $o .= '<title>' . xmlify($r->title) . '</title>' . "\r\n"; if($r->links) { - // FIXME !!! + /** @FIXME !!! */ if(substr($r->link,0,1) === '<') { if(strstr($r->link,'&') && (! strstr($r->link,'&'))) $r->link = str_replace('&','&', $r->link); @@ -654,12 +667,15 @@ function construct_activity_target($item) { return ''; } -/* limit_body_size() +/** + * @brief Limit lenght on imported system messages. + * + * The purpose of this function is to apply system message length limits to + * imported messages without including any embedded photos in the length. * - * The purpose of this function is to apply system message length limits to - * imported messages without including any embedded photos in the length + * @param string $body + * @return string|unknown */ - function limit_body_size($body) { $maxlen = get_max_import_size(); @@ -671,7 +687,6 @@ function limit_body_size($body) { $orig_body = $body; $new_body = ''; $textlen = 0; - $max_found = false; $img_start = strpos($orig_body, '[img'); $img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false); @@ -700,7 +715,6 @@ function limit_body_size($body) { $new_body = $new_body . substr($orig_body, $img_start, $img_end - $img_start); } else { - if( ($textlen + $img_end) > $maxlen ) { if($textlen < $maxlen) { $new_body = $new_body . substr($orig_body, 0, $maxlen - $textlen); @@ -836,12 +850,8 @@ function get_item_elements($x) { $arr['item_flags'] = 0; - if(array_key_exists('flags',$x) && in_array('consensus',$x['flags'])) $arr['item_flags'] |= ITEM_CONSENSUS; - - - if(array_key_exists('flags',$x) && in_array('deleted',$x['flags'])) $arr['item_restrict'] |= ITEM_DELETED; if(array_key_exists('flags',$x) && in_array('hidden',$x['flags'])) @@ -868,7 +878,6 @@ function get_item_elements($x) { return array(); } - if($arr['sig']) { $r = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", dbesc($arr['author_xchan']) @@ -885,7 +894,6 @@ function get_item_elements($x) { // and we need plaintext to do that. - if(intval($arr['item_private'])) { $arr['item_flags'] = $arr['item_flags'] | ITEM_OBSCURED; if($arr['title']) @@ -914,7 +922,6 @@ function get_item_elements($x) { } return $arr; - } @@ -998,7 +1005,6 @@ function import_author_rss($x) { } return false; - } function import_author_unknown($x) { @@ -1043,7 +1049,6 @@ function import_author_unknown($x) { } return false; - } function encode_item($item,$mirror = false) { @@ -1150,7 +1155,6 @@ function encode_item($item,$mirror = false) { logger('encode_item: ' . print_r($x,true), LOGGER_DATA); return $x; - } @@ -1174,7 +1178,7 @@ function map_scope($scope,$strip = false) { default: return 'contacts'; } -} +} function translate_scope($scope) { if(! $scope || $scope === 'public') @@ -1269,12 +1273,16 @@ function decode_tags($t) { } return $ret; } - return ''; + return ''; } -// santise a potentially complex array - +/** + * @brief Santise a potentially complex array. + * + * @param array $arr + * @return array|string + */ function activity_sanitise($arr) { if($arr) { if(is_array($arr)) { @@ -1291,11 +1299,16 @@ function activity_sanitise($arr) { return htmlspecialchars($arr, ENT_COMPAT,'UTF-8', false); } } + return ''; } -// sanitise a simple linear array - +/** + * @brief Sanitise a simple linear array. + * + * @param array $arr + * @return array|string + */ function array_sanitise($arr) { if($arr) { $ret = array(); @@ -1304,6 +1317,7 @@ function array_sanitise($arr) { } return $ret; } + return ''; } @@ -1326,7 +1340,7 @@ function encode_item_flags($item) { $ret[] = 'consensus'; if($item['item_private']) $ret[] = 'private'; - + return $ret; } @@ -1419,7 +1433,6 @@ function get_mail_elements($x) { return array(); return $arr; - } @@ -1448,15 +1461,17 @@ function get_profile_elements($x) { $arr['keywords'] = (($x['keywords'] && is_array($x['keywords'])) ? array_sanitise($x['keywords']) : array()); return $arr; - } +/** + * @param object $feed + * @param array $item + * @param[out] array $author + * @return multitype:multitype: string NULL number Ambigous <NULL, string, number> Ambigous <mixed, string> Ambigous <multitype:multitype:string Ambigous <NULL, string> , multitype:multitype:string unknown > multitype:NULL unknown + */ +function get_atom_elements($feed, $item, &$author) { - -function get_atom_elements($feed,$item,&$author) { - - - $best_photo = array(); + //$best_photo = array(); $res = array(); @@ -1531,7 +1546,7 @@ function get_atom_elements($feed,$item,&$author) { if($rawmedia && $rawmedia[0]['attribs']['']['url']) { $author['author_photo'] = strip_tags(unxmlify($rawmedia[0]['attribs']['']['url'])); } - } + } // No photo/profile-link on the item - look at the feed level @@ -1573,9 +1588,9 @@ function get_atom_elements($feed,$item,&$author) { $apps = $item->get_item_tags(NAMESPACE_STATUSNET,'notice_info'); if($apps && $apps[0]['attribs']['']['source']) { $res['app'] = strip_tags(unxmlify($apps[0]['attribs']['']['source'])); - } + } - /** + /* * If there's a copy of the body content which is guaranteed to have survived mangling in transit, use it. */ @@ -1593,10 +1608,8 @@ function get_atom_elements($feed,$item,&$author) { // create a term table item for them. For now just make sure they stay as links. $res['body'] = preg_replace('/\[bookmark(.*?)\](.*?)\[\/bookmark\]/','[url$1]$2[/url]',$res['body']); - } - $res['body'] = limit_body_size($res['body']); // It isn't certain at this point whether our content is plaintext or html and we'd be foolish to trust @@ -1620,8 +1633,6 @@ function get_atom_elements($feed,$item,&$author) { $res['body'] = purify_html($res['body']); $res['body'] = @html2bbcode($res['body']); - - } elseif(! $have_real_body) { @@ -1652,7 +1663,6 @@ function get_atom_elements($feed,$item,&$author) { ); } - $private = $item->get_item_tags(NAMESPACE_DFRN,'private'); if($private && intval($private[0]['data']) > 0) $res['item_private'] = ((intval($private[0]['data'])) ? 1 : 0); @@ -1663,12 +1673,10 @@ function get_atom_elements($feed,$item,&$author) { if($rawlocation) $res['location'] = unxmlify($rawlocation[0]['data']); - $rawcreated = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'published'); if($rawcreated) $res['created'] = unxmlify($rawcreated[0]['data']); - $rawedited = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'updated'); if($rawedited) $res['edited'] = unxmlify($rawedited[0]['data']); @@ -1735,7 +1743,7 @@ function get_atom_elements($feed,$item,&$author) { } // translate OStatus unfollow to activity streams if it happened to get selected - + if((x($res,'verb')) && ($res['verb'] === 'http://ostatus.org/schema/1.0/unfollow')) $res['verb'] = ACTIVITY_UNFOLLOW; @@ -1765,7 +1773,7 @@ function get_atom_elements($feed,$item,&$author) { 'url' => $termurl, 'term' => $termterm, ); - } + } } } @@ -1790,6 +1798,7 @@ function get_atom_elements($feed,$item,&$author) { $title = ' '; if(! $type) $type = 'application/octet-stream'; + $res['attach'][] = array('href' => $link, 'length' => $len, 'type' => $type, 'title' => $title ); } } @@ -1817,10 +1826,8 @@ function get_atom_elements($feed,$item,&$author) { // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events $obj['orig'] = xmlify($body); if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) { - $body = purify_html($body); $body = html2bbcode($body); - } $obj['content'] = $body; @@ -1838,7 +1845,7 @@ function get_atom_elements($feed,$item,&$author) { if($child[NAMESPACE_ACTIVITY]['obj_type'][0]['data']) { $res['tgt_type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data']; $obj['type'] = $child[NAMESPACE_ACTIVITY]['obj_type'][0]['data']; - } + } if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data']) $obj['id'] = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data']; if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) @@ -1849,13 +1856,12 @@ function get_atom_elements($feed,$item,&$author) { $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']; if(! $body) $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data']; + // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events $obj['orig'] = xmlify($body); if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) { - $body = purify_html($body); $body = html2bbcode($body); - } $obj['content'] = $body; @@ -1896,6 +1902,7 @@ function encode_rel_links($links) { $o .= 'media:height="' . $link['attribs'][NAMESPACE_MEDIA]['height'] . '" '; $o .= ' />' . "\n" ; } + return xmlify($o); } @@ -1915,7 +1922,7 @@ function item_store($arr,$allow_exec = false) { return $ret; } - $uplinked_comment = false; + //$uplinked_comment = false; // If a page layout is provided, ensure it exists and belongs to us. @@ -1955,8 +1962,6 @@ function item_store($arr,$allow_exec = false) { $arr['item_private'] = ((x($arr,'item_private')) ? intval($arr['item_private']) : 0 ); $arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : 0 ); - - // only detect language if we have text content, and if the post is private but not yet // obscured, make it so. @@ -1966,7 +1971,6 @@ function item_store($arr,$allow_exec = false) { // apply the input filter here - if it is obscured it has been filtered already $arr['body'] = z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']); - if(local_channel() && (! $arr['sig'])) { $channel = get_app()->get_channel(); if($channel['channel_hash'] === $arr['author_xchan']) { @@ -1995,7 +1999,6 @@ function item_store($arr,$allow_exec = false) { if($arr['body']) $arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key)); } - } if((x($arr,'object')) && is_array($arr['object'])) { @@ -2042,13 +2045,12 @@ function item_store($arr,$allow_exec = false) { $arr['public_policy'] = ((x($arr,'public_policy')) ? notags(trim($arr['public_policy'])) : '' ); $arr['comment_policy'] = ((x($arr,'comment_policy')) ? notags(trim($arr['comment_policy'])) : 'contacts' ); - + $arr['item_unseen'] = ((array_key_exists('item_unseen',$arr)) ? intval($arr['item_unseen']) : 1); if($arr['comment_policy'] == 'none') $arr['item_flags'] = $arr['item_flags'] | ITEM_NOCOMMENT; - // handle time travelers // Allow a bit of fudge in case somebody just has a slightly slow/fast clock @@ -2062,8 +2064,6 @@ function item_store($arr,$allow_exec = false) { if(! $arr['plink']) $arr['plink'] = $arr['llink']; - - if($arr['parent_mid'] === $arr['mid']) { $parent_id = 0; $parent_deleted = 0; @@ -2134,13 +2134,12 @@ function item_store($arr,$allow_exec = false) { if($r[0]['item_flags'] & ITEM_WALL) $arr['item_flags'] = $arr['item_flags'] | ITEM_WALL; - // An uplinked comment might arrive with a downstream owner. // Fix it. if($r[0]['owner_xchan'] !== $arr['owner_xchan']) { $arr['owner_xchan'] = $r[0]['owner_xchan']; - $uplinked_comment = true; +// $uplinked_comment = true; } // if the parent is private, force privacy for the entire conversation @@ -2164,8 +2163,7 @@ function item_store($arr,$allow_exec = false) { if($parent_deleted) $arr['item_restrict'] = $arr['item_restrict'] | ITEM_DELETED; - - + $r = q("SELECT `id` FROM `item` WHERE `mid` = '%s' AND `uid` = %d LIMIT 1", dbesc($arr['mid']), intval($arr['uid']) @@ -2270,7 +2268,7 @@ function item_store($arr,$allow_exec = false) { } $arr['term'] = $terms; - } + } call_hooks('post_remote_end',$arr); @@ -2337,7 +2335,7 @@ function item_store_update($arr,$allow_exec = false) { logger('item_store_update: original post not found: ' . $orig_post_id); $ret['message'] = 'no original'; return $ret; - } + } // override the unseen flag with the original @@ -2350,13 +2348,12 @@ function item_store_update($arr,$allow_exec = false) { if($orig[0]['item_flags'] & ITEM_OBSCURED) $orig[0]['item_flags'] = $orig[0]['item_flags'] ^ ITEM_OBSCURED; - $arr['item_flags'] = intval($arr['item_flags']) | $orig[0]['item_flags']; $arr['item_restrict'] = intval($arr['item_restrict']) | $orig[0]['item_restrict']; - if(array_key_exists('edit',$arr)) - unset($arr['edit']); + unset($arr['edit']); + $arr['mimetype'] = ((x($arr,'mimetype')) ? notags(trim($arr['mimetype'])) : 'text/bbcode'); if(($arr['mimetype'] == 'application/x-php') && (! $allow_exec)) { @@ -2365,19 +2362,19 @@ function item_store_update($arr,$allow_exec = false) { return $ret; } - if(! ($arr['item_flags'] & ITEM_OBSCURED)) { + if(! ($arr['item_flags'] & ITEM_OBSCURED)) { $arr['lang'] = detect_language($arr['body']); - // apply the input filter here - if it is obscured it has been filtered already - $arr['body'] = z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']); - - if(local_channel() && (! $arr['sig'])) { - $channel = get_app()->get_channel(); - if($channel['channel_hash'] === $arr['author_xchan']) { - $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey'])); - $arr['item_flags'] |= ITEM_VERIFIED; - } - } + // apply the input filter here - if it is obscured it has been filtered already + $arr['body'] = z_input_filter($arr['uid'],$arr['body'],$arr['mimetype']); + + if(local_channel() && (! $arr['sig'])) { + $channel = get_app()->get_channel(); + if($channel['channel_hash'] === $arr['author_xchan']) { + $arr['sig'] = base64url_encode(rsa_sign($arr['body'],$channel['channel_prvkey'])); + $arr['item_flags'] |= ITEM_VERIFIED; + } + } $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); @@ -2392,17 +2389,15 @@ function item_store_update($arr,$allow_exec = false) { $arr = $translate['item']; } if($arr['item_private']) { - $key = get_config('system','pubkey'); - $arr['item_flags'] = $arr['item_flags'] | ITEM_OBSCURED; - if($arr['title']) - $arr['title'] = json_encode(crypto_encapsulate($arr['title'],$key)); - if($arr['body']) - $arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key)); - } - + $key = get_config('system','pubkey'); + $arr['item_flags'] = $arr['item_flags'] | ITEM_OBSCURED; + if($arr['title']) + $arr['title'] = json_encode(crypto_encapsulate($arr['title'],$key)); + if($arr['body']) + $arr['body'] = json_encode(crypto_encapsulate($arr['body'],$key)); + } } - if((x($arr,'object')) && is_array($arr['object'])) { activity_sanitise($arr['object']); $arr['object'] = json_encode($arr['object']); @@ -2418,7 +2413,6 @@ function item_store_update($arr,$allow_exec = false) { $arr['attach'] = json_encode($arr['attach']); } - unset($arr['id']); unset($arr['uid']); unset($arr['aid']); @@ -2465,15 +2459,13 @@ function item_store_update($arr,$allow_exec = false) { $arr['app'] = ((x($arr,'app')) ? notags(trim($arr['app'])) : $orig[0]['app']); // $arr['item_restrict'] = ((x($arr,'item_restrict')) ? intval($arr['item_restrict']) : $orig[0]['item_restrict'] ); // $arr['item_flags'] = ((x($arr,'item_flags')) ? intval($arr['item_flags']) : $orig[0]['item_flags'] ); - + $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); if(x($arr,'cancel')) { @@ -2495,11 +2487,11 @@ function item_store_update($arr,$allow_exec = false) { logger('item_store_update: ' . print_r($arr,true), LOGGER_DATA); $str = ''; - foreach($arr as $k => $v) { - if($str) - $str .= ","; - $str .= " `" . $k . "` = '" . $v . "' "; - } + foreach($arr as $k => $v) { + if($str) + $str .= ","; + $str .= " `" . $k . "` = '" . $v . "' "; + } $r = dbq("update `item` set " . $str . " where id = " . $orig_post_id ); @@ -2530,7 +2522,7 @@ function item_store_update($arr,$allow_exec = false) { } $arr['term'] = $terms; - } + } call_hooks('post_remote_update_end',$arr); @@ -2568,8 +2560,9 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, $signed_text = $datarray['mid'] . ';' . $parent_item['mid'] . ';' . $signed_body . ';' . $diaspora_handle; + /** @FIXME $uprvkey is undefined, do we still need this if-statement? */ if( $uprvkey !== false ) - $authorsig = base64_encode(rsa_sign($signed_text,$channel['channel_prvkey'],'sha256')); + $authorsig = base64_encode(rsa_sign($signed_text, $channel['channel_prvkey'], 'sha256')); else $authorsig = ''; @@ -2630,7 +2623,6 @@ function send_status_notifications($post_id,$item) { $link = get_app()->get_baseurl() . '/display/' . $item['mid']; - $y = q("select id from notify where link = '%s' and uid = %d limit 1", dbesc($link), intval($item['uid']) @@ -2641,50 +2633,50 @@ function send_status_notifications($post_id,$item) { if(! $notify) return; + require_once('include/enotify.php'); notification(array( 'type' => NOTIFY_COMMENT, 'from_xchan' => $item['author_xchan'], 'to_xchan' => $r[0]['channel_hash'], 'item' => $item, - 'link' => $link, + 'link' => $link, 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, 'parent_mid' => $item['parent_mid'] )); - return; } - - - - function get_item_contact($item,$contacts) { if(! count($contacts) || (! is_array($item))) return false; + foreach($contacts as $contact) { if($contact['id'] == $item['contact-id']) { return $contact; break; // NOTREACHED } } + return false; } - -function tag_deliver($uid,$item_id) { - - // Called when we deliver things that might be tagged in ways that require delivery processing. - // Handles community tagging of posts and also look for mention tags - // and sets up a second delivery chain if appropriate - - $a = get_app(); +/** + * @brief Called when we deliver things that might be tagged in ways that require delivery processing. + * + * Handles community tagging of posts and also look for mention tags and sets up + * a second delivery chain if appropriate. + * + * @param int $uid + * @param int $item_id + */ +function tag_deliver($uid, $item_id) { $mention = false; - /** + /* * Fetch stuff we need - a channel and an item */ @@ -2693,7 +2685,7 @@ function tag_deliver($uid,$item_id) { ); if(! $u) return; - + $i = q("select * from item where id = %d and uid = %d limit 1", intval($item_id), intval($uid) @@ -2713,8 +2705,7 @@ function tag_deliver($uid,$item_id) { return; } - - /** + /* * Seems like a good place to plug in a poke notification. */ @@ -2722,7 +2713,7 @@ function tag_deliver($uid,$item_id) { $poke_notify = true; if(($item['obj_type'] == "") || ($item['obj_type'] !== ACTIVITY_OBJ_PERSON) || (! $item['object'])) - $poke_notify = false; + $poke_notify = false; $obj = json_decode_plus($item['object']); if($obj) { @@ -2732,7 +2723,6 @@ function tag_deliver($uid,$item_id) { if($item['item_restrict'] & ITEM_DELETED) $poke_notify = false; - $verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1)); if($poke_notify) { require_once('include/enotify.php'); @@ -2749,7 +2739,7 @@ function tag_deliver($uid,$item_id) { } } - /** + /* * Do community tagging */ @@ -2783,7 +2773,7 @@ function tag_deliver($uid,$item_id) { dbesc(datetime_convert()), dbesc($j_tgt['id']), intval($u[0]['channel_id']) - ); + ); proc_run('php','include/notifier.php','edit_post',$p[0]['id']); } } @@ -2793,7 +2783,7 @@ function tag_deliver($uid,$item_id) { logger('tag_deliver: tag permission denied for ' . $u[0]['channel_address']); } - /** + /* * A "union" is a message which our channel has sourced from another channel. * This sets up a second delivery chain just like forum tags do. * Find out if this is a source-able post. @@ -2819,11 +2809,10 @@ function tag_deliver($uid,$item_id) { } - /** + /* * Now we've got those out of the way. Let's see if this is a post that's tagged for re-delivery */ - $terms = get_terms_oftype($item['term'],TERM_MENTION); if($terms) @@ -2833,20 +2822,20 @@ function tag_deliver($uid,$item_id) { if($terms) { foreach($terms as $term) { - if(link_compare($term['url'],$link)) { + if(link_compare($term['url'],$link)) { $mention = true; break; } } - } + } if($mention) { logger('tag_deliver: mention found for ' . $u[0]['channel_name']); - + $r = q("update item set item_flags = ( item_flags | %d ) where id = %d", intval(ITEM_MENTIONSME), intval($item_id) - ); + ); // At this point we've determined that the person receiving this post was mentioned in it or it is a union. // Now let's check if this mention was inside a reshare so we don't spam a forum @@ -2866,6 +2855,7 @@ function tag_deliver($uid,$item_id) { $tagged = false; $plustagged = false; + $matches = array(); $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/'; if(preg_match($pattern,$body,$matches)) @@ -2898,7 +2888,7 @@ function tag_deliver($uid,$item_id) { $arr = array('channel_id' => $uid, 'item' => $item, 'body' => $body); call_hooks('tagged',$arr); - /** + /* * Kill two birds with one stone. As long as we're here, send a mention notification. */ @@ -2926,7 +2916,6 @@ function tag_deliver($uid,$item_id) { logger('tag_delivery denied for uid ' . $uid . ' and xchan ' . $item['author_xchan']); return; } - } if((! $mention) && (! $union)) { @@ -2948,25 +2937,18 @@ function tag_deliver($uid,$item_id) { logger('tag_deliver: creating second delivery chain.'); start_delivery_chain($u[0],$item,$item_id,null); - } /** - * @function tgroup_check($uid,$item) + * @brief This function is called pre-deliver to see if a post matches the criteria to be tag delivered. * - * This function is called pre-deliver to see if a post matches the criteria to be tag delivered. * We don't actually do anything except check that it matches the criteria. * 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. */ - - - function tgroup_check($uid,$item) { - $a = get_app(); - $mention = false; // check that the message originated elsewhere and is a top-level post @@ -2980,6 +2962,7 @@ function tgroup_check($uid,$item) { ); if($r) return true; + return false; } if(! perm_is_allowed($uid,$item['author_xchan'],'tag_deliver')) @@ -3001,13 +2984,12 @@ function tgroup_check($uid,$item) { if($terms) { foreach($terms as $term) { - if(link_compare($term['url'],$link)) { + if(link_compare($term['url'],$link)) { $mention = true; break; } } - } - + } if($mention) { logger('tgroup_check: mention found for ' . $u[0]['channel_name']); @@ -3029,12 +3011,12 @@ function tgroup_check($uid,$item) { $body = preg_replace('/\[share(.*?)\[\/share\]/','',$body); - // $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'] . '+','/') . '\[\/zrl\]/'; $pattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/'; $found = false; + $matches = array(); if(preg_match_all($pattern,$body,$matches,PREG_SET_ORDER)) { $max_forums = get_config('system','max_tagged_forums'); @@ -3059,7 +3041,6 @@ function tgroup_check($uid,$item) { } return true; - } /** @@ -3067,10 +3048,13 @@ function tgroup_check($uid,$item) { * receiving the post. This starts the second delivery chain, by resetting permissions and ensuring * that ITEM_UPLINK is set on the parent post, and storing the current owner_xchan as the source_xchan. * We'll become the new owner. If called without $parent, this *is* the parent post. + * + * @param array $channel + * @param array $item + * @param int $item_id + * @param boolean $parent */ - -function start_delivery_chain($channel,$item,$item_id,$parent) { - +function start_delivery_chain($channel, $item, $item_id, $parent) { // Change this copy of the post to a forum head message and deliver to all the tgroup members // also reset all the privacy bits to the forum default permissions @@ -3093,7 +3077,6 @@ function start_delivery_chain($channel,$item,$item_id,$parent) { if(! $parent) $flag_bits = $flag_bits | ITEM_ORIGIN; - // unset the nocomment bit if it's there. if($flag_bits & ITEM_NOCOMMENT) @@ -3113,7 +3096,7 @@ function start_delivery_chain($channel,$item,$item_id,$parent) { $r = q("update item set source_xchan = owner_xchan where id = %d", intval($item_id) ); - } + } $title = $item['title']; $body = $item['body']; @@ -3155,39 +3138,28 @@ function start_delivery_chain($channel,$item,$item_id,$parent) { intval($item_id) ); - - if($r) proc_run('php','include/notifier.php','tgroup',$item_id); else - logger('start_delivery_chain: failed to update item'); - - return; + logger('start_delivery_chain: failed to update item'); } - - /** - * @function check_item_source($uid,$item) - * @param $uid - * @param $item + * @brief * - * @description * Checks to see if this item owner is referenced as a source for this channel and if the post * matches the rules for inclusion in this channel. Returns true if we should create a second delivery * chain and false if none of the rules apply, or if the item is private. + * + * @param int $uid + * @param array $item */ - - -function check_item_source($uid,$item) { - - +function check_item_source($uid, $item) { $r = q("select * from source where src_channel_id = %d and ( src_xchan = '%s' or src_xchan = '*' ) limit 1", intval($uid), dbesc(($item['source_xchan']) ? $item['source_xchan'] : $item['owner_xchan']) ); - if(! $r) return false; @@ -3196,18 +3168,15 @@ function check_item_source($uid,$item) { dbesc($item['owner_xchan']) ); - if(! $x) return false; - if(! ($x[0]['abook_their_perms'] & PERMS_A_REPUBLISH)) return false; if($item['item_private'] && (! ($x[0]['abook_flags'] & ABOOK_FLAG_FEED))) return false; - if($r[0]['src_channel_xchan'] === $item['owner_xchan']) return false; @@ -3218,6 +3187,7 @@ function check_item_source($uid,$item) { $text = prepare_text($item['body'],$item['mimetype']); $text = html2plain($text); + /** @BUG $items is undefined, should this be $item? */ $tags = ((count($items['term'])) ? $items['term'] : false); $words = explode("\n",$r[0]['src_patt']); @@ -3232,12 +3202,11 @@ function check_item_source($uid,$item) { return true; } } + return false; } - - function mail_store($arr) { if(! $arr['channel_id']) { @@ -3262,7 +3231,6 @@ function mail_store($arr) { $arr['body'] = ((x($arr,'body')) ? trim($arr['body']) : ''); $arr['mail_flags'] = ((x($arr,'mail_flags')) ? intval($arr['mail_flags']) : 0 ); - if(! $arr['parent_mid']) { logger('mail_store: missing parent'); @@ -3328,9 +3296,9 @@ function mail_store($arr) { 'type' => NOTIFY_MAIL, 'item' => $arr, 'verb' => ACTIVITY_POST, - 'otype' => 'mail' + 'otype' => 'mail' ); - + notification($notif_params); } @@ -3338,35 +3306,35 @@ function mail_store($arr) { return $current_post; } - /** + * @brief Process atom feed and update anything/everything we might need to update. * - * consume_feed - process atom feed and update anything/everything we might need to update - * - * $xml = the (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds. - * - * $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. - * $contact = the person who is sending us stuff. If not set, we MAY be processing a "follow" activity - * from an external network and MAY create an appropriate contact record. Otherwise, we MUST - * have a contact record. * $hub = should we find a hub declation in the feed, pass it back to our calling process, who might (or * might not) try and subscribe to it. * $datedir sorts in reverse order - * $pass - by default ($pass = 0) we cannot guarantee that a parent item has been - * imported prior to its children being seen in the stream unless we are certain - * of how the feed is arranged/ordered. - * With $pass = 1, we only pull parent items out of the stream. - * With $pass = 2, we only pull children (comments/likes). + * + * @param array $xml + * The (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds. + * @param $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 $contact + * The person who is sending us stuff. If not set, we MAY be processing a "follow" activity + * from an external network and MAY create an appropriate contact record. Otherwise, we MUST + * have a contact record. + * @param int $pass by default ($pass = 0) we cannot guarantee that a parent item has been + * imported prior to its children being seen in the stream unless we are certain + * of how the feed is arranged/ordered. + * * With $pass = 1, we only pull parent items out of the stream. + * * With $pass = 2, we only pull children (comments/likes). * * So running this twice, first with pass 1 and then with pass 2 will do the right * thing regardless of feed ordering. This won't be adequate in a fully-threaded * model where comments can have sub-threads. That would require some massive sorting * to get all the feed items into a mostly linear ordering, and might still require - * recursion. + * recursion. */ - -function consume_feed($xml,$importer,&$contact,$pass = 0) { +function consume_feed($xml, $importer, &$contact, $pass = 0) { require_once('library/simplepie/simplepie.inc'); @@ -3403,7 +3371,6 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) { $when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s'); } - if($deleted && is_array($contact)) { $r = q("SELECT * from item where mid = '%s' and author_xchan = '%s' and uid = %d limit 1", dbesc(base64url_encode($mid)), @@ -3418,7 +3385,7 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) { logger('consume_feed: deleting item ' . $item['id'] . ' mid=' . base64url_decode($item['mid']), LOGGER_DEBUG); drop_item($item['id'],false); } - } + } } } } @@ -3449,7 +3416,6 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) { if($pass == 1) continue; - // Have we seen it? If not, import it. $item_id = base64url_encode($item->get_id()); @@ -3469,15 +3435,12 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) { $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo']))); if($x) $datarray['author_xchan'] = $x; - } if(! $datarray['author_xchan']) $datarray['author_xchan'] = $contact['xchan_hash']; - $datarray['owner_xchan'] = $contact['xchan_hash']; - $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1", dbesc($item_id), intval($importer['channel_id']) @@ -3501,15 +3464,12 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) { $datarray['parent_mid'] = $parent_mid; $datarray['uid'] = $importer['channel_id']; - - logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA); $xx = item_store($datarray); $r = $xx['item_id']; continue; } - else { // Head post of a conversation. Have we seen it? If not, import it. @@ -3538,15 +3498,12 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) { $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo']))); if($x) $datarray['author_xchan'] = $x; - } if(! $datarray['author_xchan']) $datarray['author_xchan'] = $contact['xchan_hash']; - $datarray['owner_xchan'] = $contact['xchan_hash']; - $r = q("SELECT edited FROM item WHERE mid = '%s' AND uid = %d LIMIT 1", dbesc($item_id), intval($importer['channel_id']) @@ -3568,7 +3525,6 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) { continue; } - $datarray['parent_mid'] = $item_id; $datarray['uid'] = $importer['channel_id']; @@ -3581,24 +3537,18 @@ function consume_feed($xml,$importer,&$contact,$pass = 0) { logger('consume_feed: author ' . print_r($author,true),LOGGER_DEBUG); - logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA); $xx = item_store($datarray); $r = $xx['item_id']; continue; - } } } - - } function update_feed_item($uid,$datarray) { - logger('update_feed_item: not implemented! ' . $uid . ' ' . print_r($datarray,true), LOGGER_DATA); - } @@ -3608,6 +3558,7 @@ function handle_feed($uid,$abook_id,$url) { $channel = channelx_by_n($uid); if(! $channel) return; + $x = q("select * from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d limit 1", dbesc($abook_id), intval($uid) @@ -3629,13 +3580,13 @@ function atom_author($tag,$name,$uri,$h,$w,$type,$photo) { $o = ''; if(! $tag) return $o; + $name = xmlify($name); $uri = xmlify($uri); $h = intval($h); $w = intval($w); $photo = xmlify($photo); - $o .= "<$tag>\r\n"; $o .= "<name>$name</name>\r\n"; $o .= "<uri>$uri</uri>\r\n"; @@ -3645,13 +3596,12 @@ function atom_author($tag,$name,$uri,$h,$w,$type,$photo) { call_hooks('atom_author', $o); $o .= "</$tag>\r\n"; + return $o; } function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { - $a = get_app(); - if(! $item['parent']) return; @@ -3664,7 +3614,6 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { else $body = $item['body']; - $o = "\r\n\r\n<entry>\r\n"; if(is_array($author)) @@ -3698,11 +3647,9 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { if(($item['item_private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) $o .= '<zot:private>' . (($item['item_private']) ? $item['item_private'] : 1) . '</zot:private>' . "\r\n"; - if($item['app']) $o .= '<statusnet:notice_info local_id="' . $item['id'] . '" source="' . xmlify($item['app']) . '" ></statusnet:notice_info>' . "\r\n"; - $verb = construct_verb($item); $o .= '<as:verb>' . xmlify($verb) . '</as:verb>' . "\r\n"; $actobj = construct_activity_object($item); @@ -3730,7 +3677,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { call_hooks('atom_entry', $o); $o .= '</entry>' . "\r\n"; - + return $o; } @@ -3753,7 +3700,6 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { logger('fix_private_photos: found photo ' . $image, LOGGER_DEBUG); - if(stristr($image , $site . '/photo/')) { // Only embed locally hosted photos $replace = false; @@ -3815,7 +3761,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { } } } - } + } $new_body = $new_body . substr($orig_body, 0, $img_start + $img_st_close) . $image . '[/zmg]'; $orig_body = substr($orig_body, $img_start + $img_st_close + $img_len + strlen('[/zmg]')); @@ -3836,6 +3782,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { function has_permissions($obj) { if(($obj['allow_cid'] != '') || ($obj['allow_gid'] != '') || ($obj['deny_cid'] != '') || ($obj['deny_gid'] != '')) return true; + return false; } @@ -3858,10 +3805,15 @@ function compare_permissions($obj1,$obj2) { return false; } -// returns an array of contact-ids that are allowed to see this object - +/** + * @brief Returns an array of contact-ids that are allowed to see this object. + * + * @param object $obj + * @return array + */ function enumerate_permissions($obj) { require_once('include/group.php'); + $allow_people = expand_acl($obj['allow_cid']); $allow_groups = expand_groups(expand_acl($obj['allow_gid'])); $deny_people = expand_acl($obj['deny_cid']); @@ -3869,6 +3821,7 @@ function enumerate_permissions($obj) { $recipients = array_unique(array_merge($allow_people,$allow_groups)); $deny = array_unique(array_merge($deny_people,$deny_groups)); $recipients = array_diff($recipients,$deny); + return $recipients; } @@ -3885,6 +3838,7 @@ function item_getfeedtags($item) { $ret[] = array('@',$term['url'],$term['term']); } } + return $ret; } @@ -3905,11 +3859,11 @@ function item_getfeedattach($item) { } } } + return $ret; } - function item_expire($uid,$days) { if((! $uid) || ($days < 1)) @@ -3970,7 +3924,6 @@ function item_expire($uid,$days) { } // proc_run('php',"include/notifier.php","expire","$uid"); - } function retain_item($id) { @@ -4012,7 +3965,6 @@ function drop_items($items) { function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = false) { - $a = get_app(); // locate item to be deleted @@ -4057,7 +4009,6 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal intval($item['id']) ); - $arr = array('item' => $item, 'interactive' => $interactive, 'stage' => $stage); call_hooks('drop_item', $arr ); @@ -4089,7 +4040,6 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal proc_run('php','include/notifier.php','drop',$notify_id); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); - } else { if(! $interactive) @@ -4097,14 +4047,20 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal notice( t('Permission denied.') . EOL); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); } - } -// This function does not check for permission and does not send notifications and does not check recursion. -// It merely destroys all resources associated with an item. -// Please do not use without a suitable wrapper. - -function delete_item_lowlevel($item,$stage = DROPITEM_NORMAL,$force = false) { +/** + * @warning This function does not check for permission and does not send + * notifications and does not check recursion. + * It merely destroys all resources associated with an item. + * Please do not use without a suitable wrapper. + * + * @param array $item + * @param int $stage + * @param boolean $force + * @return boolean + */ +function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) { $linked_item = (($item['resource_id']) ? true : false); @@ -4152,7 +4108,6 @@ function delete_item_lowlevel($item,$stage = DROPITEM_NORMAL,$force = false) { break; } - // immediately remove any undesired profile likes. q("delete from likes where iid = %d and channel_id = %d", @@ -4160,7 +4115,6 @@ function delete_item_lowlevel($item,$stage = DROPITEM_NORMAL,$force = false) { intval($item['uid']) ); - // network deletion request. Keep the message structure so that we can deliver delete notifications. // Come back after several days (or perhaps a month) to do the lowlevel delete (DROPITEM_PHASE2). @@ -4182,7 +4136,7 @@ function delete_item_lowlevel($item,$stage = DROPITEM_NORMAL,$force = false) { intval(TERM_OBJ_POST) ); - // FIXME remove notifications for this item + /** @FIXME remove notifications for this item */ return true; } @@ -4203,6 +4157,7 @@ function first_post_date($uid,$wall = false) { // logger('first_post_date: ' . $r[0]['id'] . ' ' . $r[0]['created'], LOGGER_DATA); return substr(datetime_convert('',date_default_timezone_get(),$r[0]['created']),0,10); } + return false; } @@ -4210,15 +4165,19 @@ function first_post_date($uid,$wall = false) { * modified posted_dates() {below} to arrange the list in years, which we'll eventually * use to make a menu of years with collapsible sub-menus for the months instead of the * current flat list of all representative dates. + * + * @param int $uid + * @param unknown $wall + * @param unknown $mindate + * @return array */ - -function list_post_dates($uid,$wall,$mindate) { +function list_post_dates($uid, $wall, $mindate) { $dnow = datetime_convert('',date_default_timezone_get(),'now','Y-m-d'); if($mindate) - $dthen = datetime_convert('',date_default_timezone_get(),$mindate); + $dthen = datetime_convert('',date_default_timezone_get(), $mindate); else - $dthen = first_post_date($uid,$wall); + $dthen = first_post_date($uid, $wall); if(! $dthen) return array(); @@ -4245,6 +4204,7 @@ function list_post_dates($uid,$wall,$mindate) { $ret[$dyear][] = array($str,$end_month,$start_month); $dnow = datetime_convert('','',$dnow . ' -1 month', 'Y-m-d'); } + return $ret; } @@ -4307,7 +4267,6 @@ function fetch_post_tags($items,$link = false) { ); } - for($x = 0; $x < count($items); $x ++) { if($tags) { foreach($tags as $t) { @@ -4338,7 +4297,6 @@ function fetch_post_tags($items,$link = false) { function zot_feed($uid,$observer_xchan,$arr) { - $result = array(); $mindate = null; $message_id = null; @@ -4351,9 +4309,9 @@ function zot_feed($uid,$observer_xchan,$arr) { $message_id = $arr['message_id']; } - if(! $mindate) $mindate = NULL_DATE; + $mindate = dbesc($mindate); logger('zot_feed: requested for uid ' . $uid . ' from observer ' . $observer_xchan, LOGGER_DEBUG); @@ -4383,7 +4341,7 @@ function zot_feed($uid,$observer_xchan,$arr) { $items = array(); - // FIXME + /** @FIXME fix this part for PostgreSQL */ if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { return array(); @@ -4426,12 +4384,10 @@ function zot_feed($uid,$observer_xchan,$arr) { $items = fetch_post_tags($items); require_once('include/conversation.php'); $items = conv_sort($items,'ascending'); - } else $items = array(); - logger('zot_feed: number items: ' . count($items),LOGGER_DEBUG); foreach($items as $item) @@ -4452,13 +4408,13 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $sql_nets = ''; $sql_options = ''; $sql_extra2 = ''; - $sql_extra3 = ''; + $sql_extra3 = ''; $def_acl = ''; $item_uids = ' true '; - + if ($arr['uid']) $uid= $arr['uid']; - + if($channel) { $uid = $channel['channel_id']; $uidhash = $channel['channel_hash']; @@ -4470,65 +4426,64 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C if($arr['wall']) $sql_options .= " and (item_flags & " . intval(ITEM_WALL) . ")>0 "; - + $sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE (item_flags & " . intval(ITEM_THREAD_TOP) . ")>0 $sql_options ) "; - + if($arr['since_id']) - $sql_extra .= " and item.id > " . $since_id . " "; - - if($arr['gid'] && $uid) { - $r = q("SELECT * FROM `groups` WHERE id = %d AND uid = %d LIMIT 1", - intval($arr['group']), - intval($uid) - ); - if(! $r) { + $sql_extra .= " and item.id > " . $since_id . " "; + + if($arr['gid'] && $uid) { + $r = q("SELECT * FROM `groups` WHERE id = %d AND uid = %d LIMIT 1", + intval($arr['group']), + intval($uid) + ); + if(! $r) { $result['message'] = t('Collection not found.'); return $result; - } + } $contact_str = ''; - $contacts = group_get_members($group); - if($contacts) { + /** @FIXME $group is undefined */ + $contacts = group_get_members($group); + if ($contacts) { foreach($contacts as $c) { if($contact_str) $contact_str .= ','; - $contact_str .= "'" . $c['xchan'] . "'"; + + $contact_str .= "'" . $c['xchan'] . "'"; } - } - else { + } else { $contact_str = ' 0 '; $result['message'] = t('Collection is empty.'); return $result; - } + } - $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str)) or allow_gid like '" . protect_sprintf('%<' . dbesc($r[0]['hash']) . '>%') . "' ) and id = parent and item_restrict = 0 ) "; + $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND (( author_xchan IN ( $contact_str ) OR owner_xchan in ( $contact_str)) or allow_gid like '" . protect_sprintf('%<' . dbesc($r[0]['hash']) . '>%') . "' ) and id = parent and item_restrict = 0 ) "; $x = group_rec_byhash($uid,$r[0]['hash']); $result['headline'] = sprintf( t('Collection: %s'),$x['name']); + } + elseif($arr['cid'] && $uid) { - } - elseif($arr['cid'] && $uid) { - - $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval(ABOOK_FLAG_BLOCKED) . ")>0 limit 1", + $r = q("SELECT abook.*, xchan.* from abook left join xchan on abook_xchan = xchan_hash where abook_id = %d and abook_channel = %d and not ( abook_flags & " . intval(ABOOK_FLAG_BLOCKED) . ")>0 limit 1", intval($arr['cid']), intval(local_channel()) - ); - if($r) { - $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval($arr['uid']) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) and item_restrict = 0 ) "; + ); + if ($r) { + $sql_extra = " AND item.parent IN ( SELECT DISTINCT parent FROM item WHERE true $sql_options AND uid = " . intval($arr['uid']) . " AND ( author_xchan = '" . dbesc($r[0]['abook_xchan']) . "' or owner_xchan = '" . dbesc($r[0]['abook_xchan']) . "' ) and item_restrict = 0 ) "; $result['headline'] = sprintf( t('Connection: %s'),$r[0]['xchan_name']); - } - else { + } else { $result['message'] = t('Connection not found.'); return $result; - } - } + } + } - if($arr['datequery']) { - $sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$arr['datequery'])))); - } - if($arr['datequery2']) { - $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$arr['datequery2'])))); - } + if ($arr['datequery']) { + $sql_extra3 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$arr['datequery'])))); + } + if ($arr['datequery2']) { + $sql_extra3 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$arr['datequery2'])))); + } if(! array_key_exists('nouveau',$arr)) { $sql_extra2 = " AND item.parent = item.id "; @@ -4542,37 +4497,33 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $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($arr['conv'] && $channel) { - $sql_extra .= sprintf(" AND parent IN (SELECT distinct parent from item where ( author_xchan like '%s' or ( item_flags & %d )>0)) ", - dbesc(protect_sprintf($uidhash)), - intval(ITEM_MENTIONSME) - ); - } - + } - if(($client_mode & CLIENT_MODE_UPDATE) && (! ($client_mode & CLIENT_MODE_LOAD))) { + if (strlen($arr['file'])) { + $sql_extra .= term_query('item',$arr['files'],TERM_FILE); + } - // only setup pagination on initial page view - $pager_sql = ''; + if ($arr['conv'] && $channel) { + $sql_extra .= sprintf(" AND parent IN (SELECT distinct parent from item where ( author_xchan like '%s' or ( item_flags & %d )>0)) ", + dbesc(protect_sprintf($uidhash)), + intval(ITEM_MENTIONSME) + ); + } - } - else { - $itemspage = (($channel) ? get_pconfig($uid,'system','itemspage') : 20); - $a->set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(get_app()->pager['itemspage']), intval(get_app()->pager['start'])); - } + if (($client_mode & CLIENT_MODE_UPDATE) && (! ($client_mode & CLIENT_MODE_LOAD))) { + // only setup pagination on initial page view + $pager_sql = ''; + } else { + $itemspage = (($channel) ? get_pconfig($uid,'system','itemspage') : 20); + $a->set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20)); + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(get_app()->pager['itemspage']), intval(get_app()->pager['start'])); + } - if(isset($arr['start']) && isset($arr['records'])) - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($arr['records']), intval($arr['start'])); + if (isset($arr['start']) && isset($arr['records'])) + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval($arr['records']), intval($arr['start'])); - if(array_key_exists('cmin',$arr) || array_key_exists('cmax',$arr)) { - if(($arr['cmin'] != 0) || ($arr['cmax'] != 99)) { + if (array_key_exists('cmin',$arr) || array_key_exists('cmax',$arr)) { + if (($arr['cmin'] != 0) || ($arr['cmax'] != 99)) { // Not everybody who shows up in the network stream will be in your address book. // By default those that aren't are assumed to have closeness = 99; but this isn't @@ -4581,33 +4532,32 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $sql_nets .= " AND "; - if($arr['cmax'] == 99) + if ($arr['cmax'] == 99) $sql_nets .= " ( "; $sql_nets .= "( abook.abook_closeness >= " . intval($arr['cmin']) . " "; $sql_nets .= " AND abook.abook_closeness <= " . intval($arr['cmax']) . " ) "; - if($cmax == 99) + if ($cmax == 99) $sql_nets .= " OR abook.abook_closeness IS NULL ) "; - } + } } - $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(); + //$start = dba_timer(); require_once('include/security.php'); $sql_extra .= item_permissions_sql($channel['channel_id']); - if($arr['pages']) + if ($arr['pages']) $item_restrict = " AND (item_restrict & " . ITEM_WEBPAGE . ") "; else $item_restrict = " AND item_restrict = 0 "; - - if($arr['nouveau'] && ($client_mode & CLIENT_MODE_LOAD) && $channel) { - // "New Item View" - show all items unthreaded in reverse created date order + if ($arr['nouveau'] && ($client_mode & CLIENT_MODE_LOAD) && $channel) { + // "New Item View" - show all items unthreaded in reverse created date order $items = q("SELECT item.*, item.id AS item_id FROM item WHERE $item_uids $item_restrict @@ -4616,22 +4566,21 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C ORDER BY item.received DESC $pager_sql " ); - require_once('include/items.php'); + require_once('include/items.php'); - xchan_query($items); + xchan_query($items); - $items = fetch_post_tags($items,true); - } - else { + $items = fetch_post_tags($items,true); + } else { - // Normal conversation view + // Normal conversation view - if($arr['order'] === 'post') + if($arr['order'] === 'post') $ordering = "created"; - else + else $ordering = "commented"; - if(($client_mode & CLIENT_MODE_LOAD) || ($client_mode == CLIENT_MODE_NORMAL)) { + if(($client_mode & CLIENT_MODE_LOAD) || ($client_mode == CLIENT_MODE_NORMAL)) { // Fetch a page full of parent items for this page @@ -4657,48 +4606,46 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C ); } - $first = dba_timer(); + //$first = dba_timer(); - // Then fetch all the children of the parents that are on this page + // Then fetch all the children of the parents that are on this page - if($r) { + if($r) { - $parents_str = ids_to_querystr($r,'item_id'); + $parents_str = ids_to_querystr($r,'item_id'); if($arr['top']) $sql_extra = ' and id = parent ' . $sql_extra; - $items = q("SELECT item.*, item.id AS item_id FROM item - WHERE $item_uids $item_restrict - AND item.parent IN ( %s ) - $sql_extra ", - dbesc($parents_str) - ); + $items = q("SELECT item.*, item.id AS item_id FROM item + WHERE $item_uids $item_restrict + AND item.parent IN ( %s ) + $sql_extra ", + dbesc($parents_str) + ); - $second = dba_timer(); + $second = dba_timer(); - xchan_query($items); + xchan_query($items); - $third = dba_timer(); + //$third = dba_timer(); - $items = fetch_post_tags($items,true); + $items = fetch_post_tags($items,true); - $fourth = dba_timer(); + //$fourth = dba_timer(); require_once('include/conversation.php'); - $items = conv_sort($items,$ordering); - - //logger('items: ' . print_r($items,true)); + $items = conv_sort($items,$ordering); - } - else { - $items = array(); - } + //logger('items: ' . print_r($items,true)); + } else { + $items = array(); + } - if($parents_str && $arr['mark_seen']) - $update_unseen = ' AND parent IN ( ' . dbesc($parents_str) . ' )'; - // FIXME finish mark unseen sql - } + if($parents_str && $arr['mark_seen']) + $update_unseen = ' AND parent IN ( ' . dbesc($parents_str) . ' )'; + /** @FIXME finish mark unseen sql */ + } return $items; } @@ -4719,7 +4666,7 @@ function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remo $pagetitle = $remote_id; } - if($page_type) { + if($page_type) { // store page info as an alternate message_id so we can access it via // https://sitename/page/$channelname/$pagetitle @@ -4747,17 +4694,17 @@ function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remo ); } } - } - /** - * change access control for item with message_id $mid and channel_id $uid + * @brief Change access control for item with message_id $mid and channel_id $uid. + * + * @param string $xchan_hash + * @param string $mid + * @param int $uid */ - - -function item_add_cid($xchan_hash,$mid,$uid) { +function item_add_cid($xchan_hash, $mid, $uid) { $r = q("select id from item where mid = '%s' and uid = %d and allow_cid like '%s'", dbesc($mid), intval($uid), @@ -4809,27 +4756,28 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, } if(strpos($access_tag,'cid:') === 0) { $str_contact_allow .= '<' . substr($access_tag,4) . '>'; - $access_tag = ''; + $access_tag = ''; } elseif(strpos($access_tag,'gid:') === 0) { $str_group_allow .= '<' . substr($access_tag,4) . '>'; - $access_tag = ''; + $access_tag = ''; } } } } - -/* - * We can't trust ITEM_ORIGIN to tell us if this is a local comment +/** + * We can't trust ITEM_ORIGIN to tell us if this is a local comment * which needs to be relayed, because it was misconfigured at one point for several * months and set for some remote items (in alternate delivery chains). This could * cause looping, so use this hackish but accurate method. + * + * @param array $item + * @return boolean */ - - function comment_local_origin($item) { - if(stripos($item['mid'],get_app()->get_hostname()) && ($item['parent'] != $item['id'])) + if(stripos($item['mid'], get_app()->get_hostname()) && ($item['parent'] != $item['id'])) return true; - return false; + + return false; } diff --git a/include/language.php b/include/language.php index ec5fa84fa..1e8528dc1 100644 --- a/include/language.php +++ b/include/language.php @@ -1,8 +1,8 @@ <?php /** - * @file + * @file include/language.php * - * @brief translation support + * @brief Translation support. * * This file contains functions to work with translations and other * language related tasks. @@ -26,7 +26,7 @@ function get_browser_language() { $langs = array(); $lang_parse = array(); - if (x($_SERVER,'HTTP_ACCEPT_LANGUAGE')) { + if (x($_SERVER, 'HTTP_ACCEPT_LANGUAGE')) { // break up string into pieces (languages and q factors) preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse); @@ -110,9 +110,12 @@ function pop_lang() { $a->language = $a->langsave; } - -// load string translation table for alternate language - +/** + * @brief Load string translation table for alternate language. + * + * @param string $lang language code in 2-letter ISO 639-1 (en, de, fr) format + * @param boolean $install (optional) default false + */ function load_translation_table($lang, $install = false) { global $a; @@ -139,14 +142,13 @@ function load_translation_table($lang, $install = false) { if(file_exists("view/local-$lang/strings.php")) { include("view/local-$lang/strings.php"); } - } /** - * @brief translate string if translation exists. + * @brief Translate string if translation exists. * * @param string $s string that should get translated - * @param string $ctx optional context to appear in po file + * @param string $ctx (optional) context to appear in po file * @return translated string if exists, otherwise return $s * */ @@ -154,37 +156,53 @@ function t($s, $ctx = '') { global $a; $cs = $ctx ? '__ctx:' . $ctx . '__ ' . $s : $s; - if(x($a->strings, $cs)) { + if (x($a->strings, $cs)) { $t = $a->strings[$cs]; + return is_array($t) ? $t[0] : $t; } + return $s; } - +/** + * @brief + * + * @param string $singular + * @param string $plural + * @param int $count + * @param string $ctx + * @return string + */ function tt($singular, $plural, $count, $ctx = ''){ $a = get_app(); - $cs = $ctx?"__ctx:".$ctx."__ ".$singular:$singular; - if(x($a->strings,$cs)) { + $cs = $ctx ? "__ctx:" . $ctx . "__ " . $singular : $singular; + if (x($a->strings,$cs)) { $t = $a->strings[$cs]; $f = 'string_plural_select_' . str_replace('-', '_', $a->language); - if(! function_exists($f)) + if (! function_exists($f)) $f = 'string_plural_select_default'; + $k = $f($count); + return is_array($t) ? $t[$k] : $t; } - - if ($count != 1){ + + if ($count != 1) { return $plural; } else { return $singular; } } -// provide a fallback which will not collide with -// a function defined in any language file - +/** + * @brief Provide a fallback which will not collide with a function defined in + * any language file. + * + * @param int $n + * @return boolean + */ function string_plural_select_default($n) { return ($n != 1); } @@ -200,25 +218,25 @@ function string_plural_select_default($n) { * returned through config['system']['language_detect_min_confidence']. * * @see http://pear.php.net/package/Text_LanguageDetect - * @param s A string to examine + * @param string $s A string to examine * @return Language code in 2-letter ISO 639-1 (en, de, fr) format */ function detect_language($s) { require_once('Text/LanguageDetect.php'); $min_length = get_config('system', 'language_detect_min_length'); - if($min_length === false) + if ($min_length === false) $min_length = LANGUAGE_DETECT_MIN_LENGTH; $min_confidence = get_config('system', 'language_detect_min_confidence'); - if($min_confidence === false) + if ($min_confidence === false) $min_confidence = LANGUAGE_DETECT_MIN_CONFIDENCE; // embedded apps have long base64 strings which will trip up the detector. $naked_body = preg_replace('/\[app\](.*?)\[\/app\]/','',$s); // strip off bbcode $naked_body = preg_replace('/\[(.+?)\]/', '', $naked_body); - if(mb_strlen($naked_body) < intval($min_length)) { + if (mb_strlen($naked_body) < intval($min_length)) { logger('string length less than ' . intval($min_length), LOGGER_DATA); return ''; } @@ -233,11 +251,11 @@ function detect_language($s) { logger('detect language exception: ' . $e->getMessage(), LOGGER_DATA); } - if((! $lng) || (! (x($lng,'language')))) { + if ((! $lng) || (! (x($lng,'language')))) { return ''; } - if($lng['confidence'] < (float) $min_confidence) { + if ($lng['confidence'] < (float) $min_confidence) { logger('detect language: confidence less than ' . (float) $min_confidence, LOGGER_DATA); return ''; } @@ -251,38 +269,37 @@ function detect_language($s) { * By default we use the localized language name. You can switch the result * to any language with the optional 2nd parameter $l. * - * $s and $l should be in 2-letter ISO 639-1 format + * $s and $l should be in 2-letter ISO 639-1 format. * * If nothing could be looked up it returns $s. * - * @param $s Language code to look up - * @param $l (optional) In which language to return the name + * @param string $s Language code to look up + * @param string $l (optional) In which language to return the name * @return string with the language name, or $s if unrecognized + * + * @todo include CommerceGuys\Intl through composer like SabreDAV. */ require_once(__DIR__ . '/../library/intl/vendor/autoload.php'); use CommerceGuys\Intl\Language\LanguageRepository; function get_language_name($s, $l = null) { // get() expects the second part to be in upper case - if(strpos($s,'-') !== false) $s = substr($s,0,2) . strtoupper(substr($s,2)); - if($l !== null && strpos($l,'-') !== false) $l = substr($l,0,2) . strtoupper(substr($l,2)); + if (strpos($s, '-') !== false) $s = substr($s, 0, 2) . strtoupper(substr($s, 2)); + if ($l !== null && strpos($l, '-') !== false) $l = substr($l, 0, 2) . strtoupper(substr($l, 2)); $languageRepository = new LanguageRepository; // Sometimes intl doesn't like the second part at all ... try { $language = $languageRepository->get($s, $l); - } - catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) { - $s = substr($s,0,2); - if($l !== null) $l = substr($s,0,2); + } catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) { + $s = substr($s, 0, 2); + if($l !== null) $l = substr($s, 0, 2); try { $language = $languageRepository->get($s, $l); - } - catch(CommerceGuys\Intl\Exception\UnknownLanguageException $e) { + } catch (CommerceGuys\Intl\Exception\UnknownLanguageException $e) { return $s; // Give up } - } + } return $language->getName(); } - diff --git a/include/network.php b/include/network.php index 6aefc0b30..a0782692e 100644 --- a/include/network.php +++ b/include/network.php @@ -1,33 +1,39 @@ -<?php /** @file */ - - +<?php +/** + * @file include/network.php + */ +/** + * @brief Returns path to CA file. + * + * @return string + */ function get_capath() { return appdirpath() . '/library/cacert.pem'; } /** - * @function z_fetch_url + * @brief fetches an URL. + * * @param string $url * URL to fetch - * @param boolean $binary = false + * @param boolean $binary default false * TRUE if asked to return binary results (file download) - * @param int $redirects = 0 + * @param int $redirects default 0 * internal use, recursion counter - * @param array $opts (optional parameters) - * 'accept_content' => supply Accept: header with 'accept_content' as the value - * 'timeout' => int seconds, default system config value or 60 seconds - * 'http_auth' => username:password - * 'novalidate' => do not validate SSL certs, default is to validate using our CA list - * 'nobody' => only return the header - * - * @returns array - * 'return_code' => HTTP return code or 0 if timeout or failure - * 'success' => boolean true (if HTTP 2xx result) or false - * 'header' => HTTP headers - * 'body' => fetched content + * @param array $opts (optional parameters) assoziative array with: + * * \b accept_content => supply Accept: header with 'accept_content' as the value + * * \b timeout => int seconds, default system config value or 60 seconds + * * \b http_auth => username:password + * * \b novalidate => do not validate SSL certs, default is to validate using our CA list + * * \b nobody => only return the header + * + * @return array an assoziative array with: + * * \e int \b return_code => HTTP return code or 0 if timeout or failure + * * \e boolean \b success => boolean true (if HTTP 2xx result) or false + * * \e string \b header => HTTP headers + * * \e string \b body => fetched content */ - function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { $ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => ""); @@ -129,14 +135,15 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { if(x($opts,'debug')) { $ret['debug'] = $curl_info; } - + @curl_close($ch); return($ret); } /** - * @function z_post_url + * @brief + * * @param string $url * URL to post * @param mixed $params @@ -151,17 +158,15 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) { * 'timeout' => int seconds, default system config value or 60 seconds * 'http_auth' => username:password * 'novalidate' => do not validate SSL certs, default is to validate using our CA list - * - * @returns array - * 'return_code' => HTTP return code or 0 if timeout or failure - * 'success' => boolean true (if HTTP 2xx result) or false - * 'header' => HTTP headers - * 'body' => fetched content + * @return array an assoziative array with: + * * \e int \b return_code => HTTP return code or 0 if timeout or failure + * * \e boolean \b success => boolean true (if HTTP 2xx result) or false + * * \e string \b header => HTTP headers + * * \e string \b body => content + * * \e string \b debug => from curl_info() */ - - function z_post_url($url,$params, $redirects = 0, $opts = array()) { - + $ret = array('return_code' => 0, 'success' => false, 'header' => "", 'body' => ""); $ch = curl_init($url); @@ -257,24 +262,35 @@ function z_post_url($url,$params, $redirects = 0, $opts = array()) { logger('z_post_url: debug: ' . print_r($curl_info,true), LOGGER_DATA); } - $ret['body'] = substr($s,strlen($header)); + $ret['body'] = substr($s, strlen($header)); $ret['header'] = $header; if(x($opts,'debug')) { $ret['debug'] = $curl_info; } - curl_close($ch); return($ret); } +/** + * @brief Like z_post_url() but with an application/json HTTP header. + * + * Add a "Content-Type: application/json" HTTP-header to $opts and call z_post_url(). + * + * @see z_post_url() + * + * @param string $url + * @param array $params + * @param number $redirects default 0 + * @param array $opts (optional) curl options + * @return z_post_url() + */ +function z_post_url_json($url, $params, $redirects = 0, $opts = array()) { -function z_post_url_json($url,$params,$redirects = 0, $opts = array()) { + $opts = array_merge($opts, array('headers' => array('Content-Type: application/json'))); - $opts = array_merge($opts,array('headers' => array('Content-Type: application/json'))); return z_post_url($url,json_encode($params),$redirects,$opts); - } @@ -305,22 +321,19 @@ function xml_status($st, $message = '') { } /** - * @function http_status_exit - * - * Send HTTP status header and exit + * @brief Send HTTP status header and exit. + * * @param int $val * integer HTTP status result value * @param string $msg * optional message * @returns (does not return, process is terminated) */ +function http_status_exit($val, $msg = '') { -function http_status_exit($val,$msg = '') { - - $err = ''; - if($val >= 400) + if ($val >= 400) $msg = (($msg) ? $msg : 'Error'); - if($val >= 200 && $val < 300) + if ($val >= 200 && $val < 300) $msg = (($msg) ? $msg : 'OK'); logger('http_status_exit ' . $val . ' ' . $msg); diff --git a/include/permissions.php b/include/permissions.php index 4d7def346..82145066b 100644 --- a/include/permissions.php +++ b/include/permissions.php @@ -1,6 +1,6 @@ <?php /** - * @file incldue/permissions.php + * @file include/permissions.php * * This file conntains functions to check and work with permissions. */ @@ -445,21 +445,21 @@ function site_default_perms() { /** - * @function get_role_perms($role) - * @param string $role - * - * Given a string for the channel role ('social','forum', etc) + * @brief Return an array of all permissions for this role. + * + * Given a string for the channel role ('social','forum', etc) * return an array of all permission fields pre-filled for this role. * This includes the channel permission scope indicators (anything beginning with 'channel_') as well as - * perms_auto: true or false to create auto-permissions for this channel - * perms_follow: The permissions to apply when initiating a connection request to another channel - * perms_accept: The permissions to apply when accepting a connection request from another channel (not automatic) - * default_collection: true or false to make the default ACL include the channel's default collection - * directory_publish: true or false to publish this channel in the directory + * * perms_auto: true or false to create auto-permissions for this channel + * * perms_follow: The permissions to apply when initiating a connection request to another channel + * * perms_accept: The permissions to apply when accepting a connection request from another channel (not automatic) + * * default_collection: true or false to make the default ACL include the channel's default collection + * * directory_publish: true or false to publish this channel in the directory * Any attributes may be extended (new roles defined) and modified (specific permissions altered) by plugins * + * @param string $role + * @return array */ - function get_role_perms($role) { $ret = array(); @@ -800,9 +800,8 @@ function get_role_perms($role) { } /** - * @brief Returns a list or roles, grouped by type + * @brief Returns a list or roles, grouped by type. * - * @param string $current The current role * @return string Returns an array of roles, grouped by type */ function get_roles() { @@ -811,7 +810,8 @@ function get_roles() { t('Community Forum') => array('forum' => t('Mostly Public'), 'forum_restricted' => t('Restricted'), 'forum_private' => t('Private')), t('Feed Republish') => array('feed' => t('Mostly Public'), 'feed_restricted' => t('Restricted')), t('Special Purpose') => array('soapbox' => t('Celebrity/Soapbox'), 'repository' => t('Group Repository')), - t('Other') => array('custom' => t('Custom/Expert Mode'))); + t('Other') => array('custom' => t('Custom/Expert Mode')) + ); return $roles; } diff --git a/include/photos.php b/include/photos.php index c4d5a33aa..1672e310a 100644 --- a/include/photos.php +++ b/include/photos.php @@ -1,10 +1,21 @@ -<?php /** @file */ +<?php +/** + * @file include/photos.php + * @brief Functions related to photo handling. + */ require_once('include/permissions.php'); require_once('include/items.php'); require_once('include/photo/photo_driver.php'); - +/** + * @brief + * + * @param array $channel + * @param array $observer + * @param array $args + * @return array + */ function photo_upload($channel, $observer, $args) { $ret = array('success' => false); @@ -18,12 +29,12 @@ function photo_upload($channel, $observer, $args) { call_hooks('photo_upload_begin', $args); - /** + /* * Determine the album to use */ - $album = $args['album']; - $newalbum = $args['newalbum']; + $album = $args['album']; + $newalbum = $args['newalbum']; logger('photo_upload: album= ' . $album . ' newalbum= ' . $newalbum , LOGGER_DEBUG); @@ -44,8 +55,7 @@ function photo_upload($channel, $observer, $args) { $str_group_deny = perms2str(((is_array($args['group_deny'])) ? $args['group_deny'] : explode(',',$args['group_deny']))); $str_contact_deny = perms2str(((is_array($args['contact_deny'])) ? $args['contact_deny'] : explode(',',$args['contact_deny']))); - - if($args['data']) { + if ($args['data']) { // allow an import from a binary string representing the image. // This bypasses the upload step and max size limit checking @@ -56,23 +66,21 @@ function photo_upload($channel, $observer, $args) { // this is going to be deleted if it exists $src = '/tmp/deletemenow'; $type = $args['type']; - } - else { + } else { $f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => ''); call_hooks('photo_upload_file',$f); - if(x($f,'src') && x($f,'filesize')) { + if (x($f,'src') && x($f,'filesize')) { $src = $f['src']; $filename = $f['filename']; $filesize = $f['filesize']; $type = $f['type']; - } - else { - $src = $_FILES['userfile']['tmp_name']; - $filename = basename($_FILES['userfile']['name']); - $filesize = intval($_FILES['userfile']['size']); - $type = $_FILES['userfile']['type']; + } else { + $src = $_FILES['userfile']['tmp_name']; + $filename = basename($_FILES['userfile']['name']); + $filesize = intval($_FILES['userfile']['size']); + $type = $_FILES['userfile']['type']; } if (! $type) @@ -82,14 +90,14 @@ function photo_upload($channel, $observer, $args) { $maximagesize = get_config('system','maximagesize'); - if(($maximagesize) && ($filesize > $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); return $ret; } - if(! $filesize) { + if (! $filesize) { $ret['message'] = t('Image file is empty.'); @unlink($src); call_hooks('photo_post_end',$ret); @@ -101,14 +109,13 @@ function photo_upload($channel, $observer, $args) { $imagedata = @file_get_contents($src); } - $r = q("select sum(size) as total from photo where aid = %d and scale = 0 ", intval($account_id) ); $limit = service_class_fetch($channel_id,'photo_upload_limit'); - if(($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) { + if (($r) && ($limit !== false) && (($r[0]['total'] + strlen($imagedata)) > $limit)) { $ret['message'] = upgrade_message(); @unlink($src); call_hooks('photo_post_end',$ret); @@ -117,7 +124,7 @@ function photo_upload($channel, $observer, $args) { $ph = photo_factory($imagedata, $type); - if(! $ph->is_valid()) { + if (! $ph->is_valid()) { $ret['message'] = t('Unable to process image'); logger('photo_upload: unable to process image'); @unlink($src); @@ -127,13 +134,12 @@ function photo_upload($channel, $observer, $args) { $exif = $ph->orient($src); - @unlink($src); $max_length = get_config('system','max_image_length'); - if(! $max_length) + if (! $max_length) $max_length = MAX_IMAGE_LENGTH; - if($max_length > 0) + if ($max_length > 0) $ph->scaleImage($max_length); $width = $ph->getWidth(); @@ -144,7 +150,7 @@ function photo_upload($channel, $observer, $args) { $photo_hash = (($args['resource_id']) ? $args['resource_id'] : photo_new_resource()); $visitor = ''; - if($channel['channel_hash'] !== $observer['xchan_hash']) + if ($channel['channel_hash'] !== $observer['xchan_hash']) $visitor = $observer['xchan_hash']; $errors = false; @@ -163,7 +169,6 @@ function photo_upload($channel, $observer, $args) { if($args['description']) $p['description'] = $args['description']; - $r1 = $ph->save($p); if(! $r1) $errors = true; @@ -214,8 +219,6 @@ function photo_upload($channel, $observer, $args) { } } - - $item_flags = ITEM_WALL|ITEM_ORIGIN|ITEM_THREAD_TOP; $item_restrict = (($visible) ? ITEM_VISIBLE : ITEM_HIDDEN); $title = ''; @@ -263,10 +266,9 @@ function photo_upload($channel, $observer, $args) { $tag = '[zmg]'; } - - $arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' - . $tag . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]' - . '[/zrl]'; + $arr['body'] = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo_hash . ']' + . $tag . z_root() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/zmg]' + . '[/zrl]'; $result = item_store($arr); $item_id = $result['item_id']; @@ -304,7 +306,7 @@ function photos_albums_list($channel, $observer) { if(! perm_is_allowed($channel_id, $observer_xchan, 'view_photos')) return false; - // FIXME - create a permissions SQL which works on arbitrary observers and channels, regardless of login or web status + /** @FIXME create a permissions SQL which works on arbitrary observers and channels, regardless of login or web status */ $sql_extra = permissions_sql($channel_id); @@ -327,7 +329,8 @@ function photos_albums_list($channel, $observer) { 'total' => $album['total'], 'url' => z_root() . '/photos/' . $channel['channel_address'] . '/album/' . bin2hex($album['album']), 'urlencode' => urlencode($album['album']), - 'bin2hex' => bin2hex($album['album'])); + 'bin2hex' => bin2hex($album['album']) + ); $ret['albums'][] = $entry; } } @@ -360,11 +363,19 @@ function photos_album_widget($channelx,$observer,$albums = null) { ? t('Upload New Photos') : '') )); } + return $o; } - -function photos_list_photos($channel,$observer,$album = '') { +/** + * @brief + * + * @param array $channel + * @param array $observer + * @param string $album default empty + * @return boolean|array + */ +function photos_list_photos($channel, $observer, $album = '') { $channel_id = $channel['channel_id']; $observer_xchan = (($observer) ? $observer['xchan_hash'] : ''); @@ -384,7 +395,7 @@ function photos_list_photos($channel,$observer,$album = '') { intval(PHOTO_NORMAL), intval(PHOTO_PROFILE) ); - + if($r) { for($x = 0; $x < count($r); $x ++) { $r[$x]['src'] = z_root() . '/photo/' . $r[$x]['resource_id'] . '-' . $r[$x]['scale']; @@ -416,6 +427,7 @@ function photos_album_exists($channel_id, $album) { * @brief Renames a photo album in a channel. * * @todo Do we need to check if new album name already exists? + * * @param int $channel_id id of the channel * @param string $oldname The name of the album to rename * @param string $newname The new name of the album @@ -429,25 +441,31 @@ function photos_album_rename($channel_id, $oldname, $newname) { ); } +/** + * @brief + * + * @param int $channel_id + * @param string $album + * @param string $remote_xchan + * @return string|boolean + */ +function photos_album_get_db_idstr($channel_id, $album, $remote_xchan = '') { -function photos_album_get_db_idstr($channel_id,$album,$remote_xchan = '') { - - if($remote_xchan) { + if ($remote_xchan) { $r = q("SELECT distinct resource_id as from photo where xchan = '%s' and uid = %d and album = '%s' ", dbesc($remote_xchan), intval($channel_id), dbesc($album) ); - } - else { + } else { $r = q("SELECT distinct resource_id from photo where uid = %d and album = '%s' ", intval($channel_id), dbesc($album) ); } - if($r) { + if ($r) { $arr = array(); - foreach($r as $rr) { + foreach ($r as $rr) { $arr[] = "'" . dbesc($rr['resource_id']) . "'" ; } $str = implode(',',$arr); @@ -457,6 +475,15 @@ function photos_album_get_db_idstr($channel_id,$album,$remote_xchan = '') { return false; } +/** + * @brief Creates a new photo item. + * + * @param array $channel + * @param string $creator_hash + * @param array $photo + * @param boolean $visible default false + * @return int item_id + */ function photos_create_item($channel, $creator_hash, $photo, $visible = false) { // Create item container @@ -506,7 +533,6 @@ function getGps($exifCoord, $hemi) { $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1; return floatval($flip * ($degrees + ($minutes / 60) + ($seconds / 3600))); - } function gps2Num($coordPart) { @@ -521,4 +547,3 @@ function gps2Num($coordPart) { return floatval($parts[0]) / floatval($parts[1]); } - diff --git a/include/plugin.php b/include/plugin.php index b6cfc8d89..4d8405b62 100755 --- a/include/plugin.php +++ b/include/plugin.php @@ -7,13 +7,12 @@ require_once("include/smarty.php"); + /** * @brief unloads an addon. * * @param string $plugin name of the addon - * @return void */ - function unload_plugin($plugin){ logger("Addons: unloading " . $plugin, LOGGER_DEBUG); @@ -28,9 +27,8 @@ function unload_plugin($plugin){ * @brief uninstalls an addon. * * @param string $plugin name of the addon - * @return bool + * @return boolean */ - function uninstall_plugin($plugin) { unload_plugin($plugin); @@ -70,7 +68,7 @@ function install_plugin($plugin) { $plugin_admin = (function_exists($plugin . '_plugin_admin') ? 1 : 0); - $r = q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ", + q("INSERT INTO `addon` (`name`, `installed`, `timestamp`, `plugin_admin`) VALUES ( '%s', 1, %d , %d ) ", dbesc($plugin), intval($t), $plugin_admin @@ -196,6 +194,7 @@ function register_hook($hook, $file, $function, $priority = 0) { dbesc($function), dbesc($priority) ); + return $r; } @@ -206,7 +205,7 @@ function register_hook($hook, $file, $function, $priority = 0) { * @param string $hook the name of the hook * @param string $file the name of the file that hooks into * @param string $function the name of the function that the hook called - * @return mixed + * @return array */ function unregister_hook($hook, $file, $function) { $r = q("DELETE FROM hook WHERE hook = '%s' AND `file` = '%s' AND `function` = '%s'", @@ -214,6 +213,7 @@ function unregister_hook($hook, $file, $function) { dbesc($file), dbesc($function) ); + return $r; } @@ -243,8 +243,7 @@ function load_hooks() { } /** - * - * @function insert_hook($hook,$fn) + * @brief Inserts a hook into a page request. * * Insert a short-lived hook into the running page request. * Hooks are normally persistent so that they can be called @@ -255,9 +254,9 @@ function load_hooks() { * which will not persist beyond the life of this page request * or the current process. * - * @param string $hook; + * @param string $hook * name of hook to attach callback - * @param string $fn; + * @param string $fn * function name of callback handler */ function insert_hook($hook, $fn) { @@ -305,9 +304,10 @@ function call_hooks($name, &$data = null) { /** - * @brief parse plugin comment in search of plugin infos. + * @brief Parse plugin comment in search of plugin infos. * * like + * \code * * Name: Plugin * * Description: A plugin which plugs in * * Version: 1.2.3 @@ -315,7 +315,7 @@ function call_hooks($name, &$data = null) { * * Author: Jane <email> * * Compat: Red [(version)], Friendica [(version)] * * - * + *\endcode * @param string $plugin the name of the plugin * @return array with the plugin information */ @@ -363,9 +363,10 @@ function get_plugin_info($plugin){ /** - * @brief parse theme comment in search of theme infos. + * @brief Parse theme comment in search of theme infos. * * like + * \code * * Name: My Theme * * Description: My Cool Theme * * Version: 1.2.3 @@ -373,7 +374,7 @@ function get_plugin_info($plugin){ * * Maintainer: Jane <profile url> * * Compat: Friendica [(version)], Red [(version)] * * - * + * \endcode * @param string $theme the name of the theme * @return array */ @@ -456,13 +457,11 @@ function get_theme_screenshot($theme) { return($a->get_baseurl() . '/images/blank.png'); } - /** - * @brief add CSS to <head> + * @brief add CSS to \<head\> * * @param string $src * @param string $media change media attribute (default to 'screen') - * @return void */ function head_add_css($src, $media = 'screen') { get_app()->css_sources[] = array($src, $media); @@ -471,21 +470,23 @@ function head_add_css($src, $media = 'screen') { function head_remove_css($src, $media = 'screen') { $a = get_app(); $index = array_search(array($src, $media), $a->css_sources); - if($index !== false) + if ($index !== false) unset($a->css_sources[$index]); } function head_get_css() { $str = ''; $sources = get_app()->css_sources; - if(count($sources)) - foreach($sources as $source) + if (count($sources)) { + foreach ($sources as $source) $str .= format_css_if_exists($source); + } + return $str; } function format_css_if_exists($source) { - if(strpos($source[0], '/') !== false) + if (strpos($source[0], '/') !== false) $path = $source[0]; else $path = theme_include($source[0]); @@ -592,6 +593,7 @@ function theme_include($file, $root = '') { if(file_exists($p)) return $p; } + return ''; } diff --git a/include/template_processor.php b/include/template_processor.php index 74acc9c67..d2bf283e3 100755 --- a/include/template_processor.php +++ b/include/template_processor.php @@ -1,305 +1,307 @@ <?php - require_once 'include/ITemplateEngine.php'; - - define ("KEY_NOT_EXISTS", '^R_key_not_Exists^'); - - class Template implements ITemplateEngine { - static $name ="internal"; - - var $r; - var $search; - var $replace; - var $stack = array(); - var $nodes = array(); - var $done = false; - var $d = false; - var $lang = null; - var $debug=false; - - private function _preg_error(){ - - switch(preg_last_error()){ - case PREG_INTERNAL_ERROR: echo('PREG_INTERNAL_ERROR'); break; - case PREG_BACKTRACK_LIMIT_ERROR: echo('PREG_BACKTRACK_LIMIT_ERROR'); break; - case PREG_RECURSION_LIMIT_ERROR: echo('PREG_RECURSION_LIMIT_ERROR'); break; - case PREG_BAD_UTF8_ERROR: echo('PREG_BAD_UTF8_ERROR'); break; +require_once 'include/ITemplateEngine.php'; + +define ("KEY_NOT_EXISTS", '^R_key_not_Exists^'); + +class Template implements ITemplateEngine { + static $name ="internal"; + + var $r; + var $search; + var $replace; + var $stack = array(); + var $nodes = array(); + var $done = false; + var $d = false; + var $lang = null; + var $debug=false; + + private function _preg_error() { + switch(preg_last_error()) { + case PREG_INTERNAL_ERROR: echo('PREG_INTERNAL_ERROR'); break; + case PREG_BACKTRACK_LIMIT_ERROR: echo('PREG_BACKTRACK_LIMIT_ERROR'); break; + case PREG_RECURSION_LIMIT_ERROR: echo('PREG_RECURSION_LIMIT_ERROR'); break; + case PREG_BAD_UTF8_ERROR: echo('PREG_BAD_UTF8_ERROR'); break; // This is only valid for php > 5.3, not certain how to code around it for unit tests -// case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break; - default: - //die("Unknown preg error."); - return; - } - echo "<hr><pre>"; - debug_print_backtrace(); - die(); +// case PREG_BAD_UTF8_OFFSET_ERROR: echo('PREG_BAD_UTF8_OFFSET_ERROR'); break; + default: + //die("Unknown preg error."); + return; } - - - private function _push_stack(){ - $this->stack[] = array($this->r, $this->nodes); - } - private function _pop_stack(){ - list($this->r, $this->nodes) = array_pop($this->stack); - - } - - private function _get_var($name, $retNoKey=false){ - $keys = array_map('trim',explode(".",$name)); - if ($retNoKey && !array_key_exists($keys[0], $this->r)) return KEY_NOT_EXISTS; - $val = $this->r; - foreach($keys as $k) { - $val = (isset($val[$k]) ? $val[$k] : null); - } - return template_escape($val); + echo "<hr><pre>"; + debug_print_backtrace(); + die(); + } + + private function _push_stack() { + $this->stack[] = array($this->r, $this->nodes); + } + + private function _pop_stack(){ + list($this->r, $this->nodes) = array_pop($this->stack); + } + + private function _get_var($name, $retNoKey=false) { + $keys = array_map('trim',explode(".",$name)); + if ($retNoKey && !array_key_exists($keys[0], $this->r)) + return KEY_NOT_EXISTS; + + $val = $this->r; + foreach($keys as $k) { + $val = (isset($val[$k]) ? $val[$k] : null); } - - /** - * IF node - * - * {{ if <$var> }}...[{{ else }} ...] {{ endif }} - * {{ if <$var>==<val|$var> }}...[{{ else }} ...]{{ endif }} - * {{ if <$var>!=<val|$var> }}...[{{ else }} ...]{{ endif }} - */ - private function _replcb_if($args){ - if (strpos($args[2],"==")>0){ - list($a,$b) = array_map("trim",explode("==",$args[2])); - $a = $this->_get_var($a); - if ($b[0]=="$") $b = $this->_get_var($b); - $val = ($a == $b); - } else if (strpos($args[2],"!=")>0){ - list($a,$b) = array_map("trim", explode("!=",$args[2])); - $a = $this->_get_var($a); - if ($b[0]=="$") $b = $this->_get_var($b); - $val = ($a != $b); - } else { - $val = $this->_get_var($args[2]); - } - $x = preg_split("|{{ *else *}}|", $args[3]); - return ( ($val) ? $x[0] : (isset($x[1]) ? $x[1] : "")); + + return template_escape($val); + } + + /** + * IF node + * \code + * {{ if <$var> }}...[{{ else }} ...] {{ endif }} + * {{ if <$var>==<val|$var> }}...[{{ else }} ...]{{ endif }} + * {{ if <$var>!=<val|$var> }}...[{{ else }} ...]{{ endif }} + * \endcode + */ + private function _replcb_if($args) { + if (strpos($args[2],"==")>0){ + list($a,$b) = array_map("trim",explode("==",$args[2])); + $a = $this->_get_var($a); + if ($b[0]=="$") $b = $this->_get_var($b); + $val = ($a == $b); + } else if (strpos($args[2],"!=")>0){ + list($a,$b) = array_map("trim", explode("!=",$args[2])); + $a = $this->_get_var($a); + if ($b[0]=="$") $b = $this->_get_var($b); + $val = ($a != $b); + } else { + $val = $this->_get_var($args[2]); } - - /** - * FOR node - * - * {{ for <$var> as $name }}...{{ endfor }} - * {{ for <$var> as $key=>$name }}...{{ endfor }} - */ - private function _replcb_for($args){ - $m = array_map('trim', explode(" as ", $args[2])); - $x = explode("=>",$m[1]); - if (count($x) == 1) { - $varname = $x[0]; - $keyname = ""; - } else { - list($keyname, $varname) = $x; - } - if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ; - //$vals = $this->r[$m[0]]; - $vals = $this->_get_var($m[0]); - $ret=""; - if (!is_array($vals)) return $ret; - foreach ($vals as $k=>$v){ - $this->_push_stack(); - $r = $this->r; - $r[$varname] = $v; - if ($keyname!='') $r[$keyname] = (($k === 0) ? '0' : $k); - $ret .= $this->replace($args[3], $r); - $this->_pop_stack(); - } - return $ret; + $x = preg_split("|{{ *else *}}|", $args[3]); + + return ( ($val) ? $x[0] : (isset($x[1]) ? $x[1] : "")); + } + + /** + * FOR node + * \code + * {{ for <$var> as $name }}...{{ endfor }} + * {{ for <$var> as $key=>$name }}...{{ endfor }} + * \endcode + */ + private function _replcb_for($args) { + $m = array_map('trim', explode(" as ", $args[2])); + $x = explode("=>",$m[1]); + if (count($x) == 1) { + $varname = $x[0]; + $keyname = ""; + } else { + list($keyname, $varname) = $x; } + if ($m[0]=="" || $varname=="" || is_null($varname)) die("template error: 'for ".$m[0]." as ".$varname."'") ; + //$vals = $this->r[$m[0]]; + $vals = $this->_get_var($m[0]); + $ret=""; + if (!is_array($vals)) return $ret; - /** - * INC node - * - * {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }} - */ - private function _replcb_inc($args){ - if (strpos($args[2],"with")) { - list($tplfile, $newctx) = array_map('trim', explode("with",$args[2])); - } else { - $tplfile = trim($args[2]); - $newctx = null; - } - - if ($tplfile[0]=="$") $tplfile = $this->_get_var($tplfile); - + foreach ($vals as $k=>$v){ $this->_push_stack(); $r = $this->r; - if (!is_null($newctx)) { - list($a,$b) = array_map('trim', explode("=",$newctx)); - $r[$a] = $this->_get_var($b); - } - $this->nodes = Array(); - $tpl = get_markup_template($tplfile); - $ret = $this->replace($tpl, $r); + $r[$varname] = $v; + if ($keyname!='') $r[$keyname] = (($k === 0) ? '0' : $k); + $ret .= $this->replace($args[3], $r); $this->_pop_stack(); - return $ret; - } - - /** - * DEBUG node - * - * {{ debug $var [$var [$var [...]]] }}{{ enddebug }} - * - * replace node with <pre>var_dump($var, $var, ...);</pre> - */ - private function _replcb_debug($args){ - $vars = array_map('trim', explode(" ",$args[2])); - $vars[] = $args[1]; - - $ret = "<pre>"; - foreach ($vars as $var){ - $ret .= htmlspecialchars(var_export( $this->_get_var($var), true )); - $ret .= "\n"; - } - $ret .= "</pre>"; - return $ret; + + return $ret; + } + + /** + * INC node + * \code + * {{ inc <templatefile> [with $var1=$var2] }}{{ endinc }} + * \endcode + */ + private function _replcb_inc($args) { + if (strpos($args[2],"with")) { + list($tplfile, $newctx) = array_map('trim', explode("with",$args[2])); + } else { + $tplfile = trim($args[2]); + $newctx = null; } - private function _replcb_node($m) { - $node = $this->nodes[$m[1]]; - if (method_exists($this, "_replcb_".$node[1])){ - $s = call_user_func(array($this, "_replcb_".$node[1]), $node); - } else { - $s = ""; - } - $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); - return $s; + if ($tplfile[0]=="$") $tplfile = $this->_get_var($tplfile); + + $this->_push_stack(); + $r = $this->r; + if (!is_null($newctx)) { + list($a,$b) = array_map('trim', explode("=",$newctx)); + $r[$a] = $this->_get_var($b); + } + $this->nodes = Array(); + $tpl = get_markup_template($tplfile); + $ret = $this->replace($tpl, $r); + $this->_pop_stack(); + + return $ret; + } + + /** + * DEBUG node + * \code + * {{ debug $var [$var [$var [...]]] }}{{ enddebug }} + * \endcode + * replace node with <pre>var_dump($var, $var, ...);</pre> + */ + private function _replcb_debug($args) { + $vars = array_map('trim', explode(" ",$args[2])); + $vars[] = $args[1]; + + $ret = "<pre>"; + foreach ($vars as $var){ + $ret .= htmlspecialchars(var_export( $this->_get_var($var), true )); + $ret .= "\n"; } - - private function _replcb($m){ - //var_dump(array_map('htmlspecialchars', $m)); - $this->done = false; - $this->nodes[] = (array) $m; - return "||". (count($this->nodes)-1) ."||"; + $ret .= "</pre>"; + + return $ret; + } + + private function _replcb_node($m) { + $node = $this->nodes[$m[1]]; + if (method_exists($this, "_replcb_".$node[1])){ + $s = call_user_func(array($this, "_replcb_".$node[1]), $node); + } else { + $s = ""; } - - private function _build_nodes($s){ - $this->done = false; - while (!$this->done){ - $this->done=true; - $s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s); - if ($s==Null) $this->_preg_error(); - } - //({{ *else *}}[^{]*)? - krsort($this->nodes); - return $s; + $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); + + return $s; + } + + private function _replcb($m) { + //var_dump(array_map('htmlspecialchars', $m)); + $this->done = false; + $this->nodes[] = (array) $m; + + return "||". (count($this->nodes)-1) ."||"; + } + + private function _build_nodes($s) { + $this->done = false; + while (!$this->done) { + $this->done=true; + $s = preg_replace_callback('|{{ *([a-z]*) *([^}]*)}}([^{]*({{ *else *}}[^{]*)?){{ *end\1 *}}|', array($this, "_replcb"), $s); + if ($s==Null) $this->_preg_error(); } - - - private function var_replace($s){ - $m = array(); - /** regexp: - * \$ literal $ - * (\[)? optional open square bracket - * ([a-zA-Z0-9-_]+\.?)+ var name, followed by optional - * dot, repeated at least 1 time - * (?(1)\]) if there was opened square bracket - * (subgrup 1), match close bracket - */ - if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(?(1)\])/', $s,$m)){ - foreach($m[0] as $var){ - - $exp = str_replace(array("[", "]"), array("", ""), $var); - $exptks = explode("|", $exp); - - $varn = $exptks[0]; - unset($exptks[0]); - $val = $this->_get_var($varn, true); - if ($val != KEY_NOT_EXISTS) { - /* run filters */ - /* - * Filter are in form of: - * filtername:arg:arg:arg - * - * "filtername" is function name - * "arg"s are optional, var value is appended to the end - * if one "arg"==='x' , is replaced with var value - * - * examples: - * $item.body|htmlspecialchars // escape html chars - * $item.body|htmlspecialchars|strtoupper // escape html and uppercase result - * $item.created|date:%Y %M %j // format date (created is a timestamp) - * $item.body|str_replace:cat:dog // replace all "cat" with "dog" - * $item.body|str_replace:cat:dog:x:1 // replace one "cat" with "dog" - - */ - foreach ($exptks as $filterstr) { - $filter = explode(":", $filterstr); - $filtername = $filter[0]; - unset($filter[0]); - $valkey = array_search("x", $filter); - if ($valkey === false) { - $filter[] = $val; - } else { - $filter[$valkey] = $val; - } - if (function_exists($filtername)) { - $val = call_user_func_array($filtername, $filter); - } - } - $s = str_replace($var, $val, $s); + //({{ *else *}}[^{]*)? + krsort($this->nodes); + + return $s; + } + private function var_replace($s) { + $m = array(); + /** regexp: + * \$ literal $ + * (\[)? optional open square bracket + * ([a-zA-Z0-9-_]+\.?)+ var name, followed by optional + * dot, repeated at least 1 time + * (?(1)\]) if there was opened square bracket + * (subgrup 1), match close bracket + */ + if (preg_match_all('/\$(\[)?([a-zA-Z0-9-_]+\.?)+(?(1)\])/', $s,$m)) { + foreach ($m[0] as $var) { + $exp = str_replace(array("[", "]"), array("", ""), $var); + $exptks = explode("|", $exp); + + $varn = $exptks[0]; + unset($exptks[0]); + $val = $this->_get_var($varn, true); + if ($val != KEY_NOT_EXISTS) { + /* run filters */ + /* + * Filter are in form of: + * filtername:arg:arg:arg + * + * "filtername" is function name + * "arg"s are optional, var value is appended to the end + * if one "arg"==='x' , is replaced with var value + * + * examples: + * $item.body|htmlspecialchars // escape html chars + * $item.body|htmlspecialchars|strtoupper // escape html and uppercase result + * $item.created|date:%Y %M %j // format date (created is a timestamp) + * $item.body|str_replace:cat:dog // replace all "cat" with "dog" + * $item.body|str_replace:cat:dog:x:1 // replace one "cat" with "dog" + */ + foreach ($exptks as $filterstr) { + $filter = explode(":", $filterstr); + $filtername = $filter[0]; + unset($filter[0]); + $valkey = array_search("x", $filter); + if ($valkey === false) { + $filter[] = $val; + } else { + $filter[$valkey] = $val; + } + if (function_exists($filtername)) { + $val = call_user_func_array($filtername, $filter); + } } + $s = str_replace($var, $val, $s); } } - - return $s; - } - - private function replace($s,$r) { - $this->replace_macros($s, $r); - } - - // TemplateEngine interface - public function replace_macros($s, $r) { - $this->r = $r; - - $s = $this->_build_nodes($s); - - $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); - if ($s==Null) $this->_preg_error(); - - // remove comments block - $s = preg_replace('/{#[^#]*#}/', "" , $s); - - $t2 = dba_timer(); - - // replace strings recursively (limit to 10 loops) - $os = ""; $count=0; - while(($os !== $s) && $count<10){ - $os=$s; $count++; - $s = $this->var_replace($s); - } - return $s; } - public function get_markup_template($file, $root='') { - $template_file = theme_include($file, $root); - if ($template_file) { - $content = file_get_contents($template_file); - } - return $content; - } + return $s; } - + private function replace($s, $r) { + $this->replace_macros($s, $r); + } + // TemplateEngine interface + public function replace_macros($s, $r) { + $this->r = $r; + $s = $this->_build_nodes($s); -function template_escape($s) { + $s = preg_replace_callback('/\|\|([0-9]+)\|\|/', array($this, "_replcb_node"), $s); + if ($s == Null) + $this->_preg_error(); - return str_replace(array('$','{{'),array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),$s); + // remove comments block + $s = preg_replace('/{#[^#]*#}/', "" , $s); + //$t2 = dba_timer(); -} + // replace strings recursively (limit to 10 loops) + $os = ""; + $count=0; + while (($os !== $s) && $count<10) { + $os=$s; + $count++; + $s = $this->var_replace($s); + } -function template_unescape($s) { + return $s; + } - return str_replace(array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),array('$','{{'),$s); + public function get_markup_template($file, $root='') { + $template_file = theme_include($file, $root); + if ($template_file) { + $content = file_get_contents($template_file); + } + return $content; + } +} +function template_escape($s) { + return str_replace(array('$','{{'),array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),$s); +} + +function template_unescape($s) { + return str_replace(array('!_Doll^Ars1Az_!','!_DoubLe^BraceS4Rw_!'),array('$','{{'),$s); } diff --git a/include/text.php b/include/text.php index 75125c606..664d5f83d 100644 --- a/include/text.php +++ b/include/text.php @@ -1,18 +1,26 @@ -<?php /** @file */ - +<?php +/** + * @file include/text.php + */ require_once("include/template_processor.php"); require_once("include/smarty.php"); +// random string, there are 86 characters max in text mode, 128 for hex +// output is urlsafe + +define('RANDOM_STRING_HEX', 0x00 ); +define('RANDOM_STRING_TEXT', 0x01 ); + /** - * This is our template processor + * @brief This is our template processor. * * @param string|FriendicaSmarty $s the string requiring macro substitution, - * or an instance of FriendicaSmarty + * or an instance of FriendicaSmarty * @param array $r key value pairs (search => replace) * @return string substituted string */ -function replace_macros($s,$r) { +function replace_macros($s, $r) { $a = get_app(); $arr = array('template' => $s, 'params' => $r); @@ -24,40 +32,38 @@ function replace_macros($s,$r) { return $output; } - -// random string, there are 86 characters max in text mode, 128 for hex -// output is urlsafe - -define('RANDOM_STRING_HEX', 0x00 ); -define('RANDOM_STRING_TEXT', 0x01 ); - - -function random_string($size = 64,$type = RANDOM_STRING_HEX) { +/** + * @brief Generates a random string. + * + * @param number $size + * @param int $type + * @return string + */ +function random_string($size = 64, $type = RANDOM_STRING_HEX) { // generate a bit of entropy and run it through the whirlpool $s = hash('whirlpool', (string) rand() . uniqid(rand(),true) . (string) rand(),(($type == RANDOM_STRING_TEXT) ? true : false)); $s = (($type == RANDOM_STRING_TEXT) ? str_replace("\n","",base64url_encode($s,true)) : $s); - return(substr($s,0,$size)); + + return(substr($s, 0, $size)); } /** - * This is our primary input filter. + * @brief This is our primary input filter. * * The high bit hack only involved some old IE browser, forget which (IE5/Mac?) * that had an XSS attack vector due to stripping the high-bit on an 8-bit character * after cleansing, and angle chars with the high bit set could get through as markup. - * + * * This is now disabled because it was interfering with some legitimate unicode sequences * and hopefully there aren't a lot of those browsers left. * * Use this on any text input where angle chars are not valid or permitted * They will be replaced with safer brackets. This may be filtered further - * if these are not allowed either. + * if these are not allowed either. * * @param string $string Input string * @return string Filtered string */ - - function notags($string) { return(str_replace(array("<",">"), array('[',']'), $string)); @@ -105,7 +111,6 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') { return purify_html($s); return escape_tags($s); - } @@ -114,39 +119,38 @@ function purify_html($s) { require_once('library/HTMLPurifier.auto.php'); require_once('include/html2bbcode.php'); -// FIXME this function has html output, not bbcode - so safely purify these -// $s = html2bb_video($s); -// $s = oembed_html2bbcode($s); +/** + * @FIXME this function has html output, not bbcode - so safely purify these + * $s = html2bb_video($s); + * $s = oembed_html2bbcode($s); + */ $config = HTMLPurifier_Config::createDefault(); $config->set('Cache.DefinitionImpl', null); $config->set('Attr.EnableID', true); $purifier = new HTMLPurifier($config); + return $purifier->purify($s); } - - -// generate a string that's random, but usually pronounceable. -// used to generate initial passwords - - /** - * generate a string that's random, but usually pronounceable. - * used to generate initial passwords + * @brief generate a string that's random, but usually pronounceable. + * + * Used to generate initial passwords. + * * @param int $len * @return string */ function autoname($len) { - if($len <= 0) + if ($len <= 0) return ''; $vowels = array('a','a','ai','au','e','e','e','ee','ea','i','ie','o','ou','u'); - if(mt_rand(0,5) == 4) + if (mt_rand(0, 5) == 4) $vowels[] = 'y'; $cons = array( @@ -178,8 +182,8 @@ function autoname($len) { $noend = array('bl', 'br', 'cl','cr','dr','fl','fr','gl','gr', 'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh'); - $start = mt_rand(0,2); - if($start == 0) + $start = mt_rand(0, 2); + if ($start == 0) $table = $vowels; else $table = $cons; @@ -190,33 +194,30 @@ function autoname($len) { $r = mt_rand(0,count($table) - 1); $word .= $table[$r]; - if($table == $vowels) - $table = array_merge($cons,$midcons); + if ($table == $vowels) + $table = array_merge($cons, $midcons); else $table = $vowels; - } $word = substr($word,0,$len); - foreach($noend as $noe) { - if((strlen($word) > 2) && (substr($word,-2) == $noe)) { + foreach ($noend as $noe) { + if ((strlen($word) > 2) && (substr($word,-2) == $noe)) { $word = substr($word,0,-1); break; } } - if(substr($word,-1) == 'q') - $word = substr($word,0,-1); + if (substr($word, -1) == 'q') + $word = substr($word, 0, -1); + return $word; } -// escape text ($str) for XML transport -// returns escaped text. - - /** - * escape text ($str) for XML transport + * @brief escape text ($str) for XML transport + * * @param string $str * @return string Escaped text. */ @@ -228,7 +229,6 @@ function xmlify($str) { $char = mb_substr($str,$x,1); switch( $char ) { - case "\r" : break; case "&" : @@ -252,9 +252,10 @@ function xmlify($str) { default : $buffer .= $char; break; - } + } } $buffer = trim($buffer); + return($buffer); } @@ -268,10 +269,12 @@ function unxmlify($s) { return $ret; } -// convenience wrapper, reverse the operation "bin2hex" - -// This is a built-in function in php >= 5.4 - +/** + * Convenience wrapper, reverse the operation "bin2hex" + * This is a built-in function in php >= 5.4 + * + * @FIXME We already have php >= 5.4 requirements, so can we remove this? + */ if(! function_exists('hex2bin')) { function hex2bin($s) { if(! (is_string($s) && strlen($s))) @@ -381,14 +384,16 @@ function alt_pager(&$a, $i, $more = '', $less = '') { } -// Turn user/group ACLs stored as angle bracketed text into arrays - - +/** + * @brief Turn user/group ACLs stored as angle bracketed text into arrays. + * + * turn string array of angle-bracketed elements into string array + * e.g. "<123xyz><246qyo><sxo33e>" => array(123xyz,246qyo,sxo33e); + * + * @param string $s + * @return array + */ function expand_acl($s) { - - // turn string array of angle-bracketed elements into string array - // e.g. "<123xyz><246qyo><sxo33e>" => array(123xyz,246qyo,sxo33e); - $ret = array(); if(strlen($s)) { @@ -399,34 +404,41 @@ function expand_acl($s) { $ret[] = $aa; } } + return $ret; } -// Used to wrap ACL elements in angle brackets for storage - - +/** + * @brief Used to wrap ACL elements in angle brackets for storage. + * + * @param[in,out] array &$item + */ function sanitise_acl(&$item) { - if(strlen($item)) + if (strlen($item)) $item = '<' . notags(trim($item)) . '>'; else unset($item); } - -// Convert an ACL array to a storable string - +/** + * @brief Convert an ACL array to a storable string. + * + * @param array $p + * @return array + */ function perms2str($p) { $ret = ''; - if(is_array($p)) + if (is_array($p)) $tmp = $p; else - $tmp = explode(',',$p); + $tmp = explode(',', $p); - if(is_array($tmp)) { - array_walk($tmp,'sanitise_acl'); - $ret = implode('',$tmp); + if (is_array($tmp)) { + array_walk($tmp, 'sanitise_acl'); + $ret = implode('', $tmp); } + return $ret; } @@ -858,51 +870,48 @@ function valid_email($x){ return false; } - /** + * @brief Replace naked text hyperlink with HTML formatted hyperlink. * - * Function: linkify - * - * Replace naked text hyperlink with HTML formatted hyperlink - * + * @param string $s + * @param boolean $me (optional) default false + * @return string */ - - -function linkify($s,$me = false) { +function linkify($s, $me = false) { $s = preg_replace("/(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\@\~\#\'\%\$\!\+\,\@]*)/", (($me) ? ' <a href="$1" rel="me" >$1</a>' : ' <a href="$1" >$1</a>'), $s); $s = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$s); + return($s); } - /** - * @function sslify($s) - * Replace media element using http url with https to a local redirector if using https locally - * @param string $s + * @brief Replace media element using http url with https to a local redirector + * if using https locally. * * Looks for HTML tags containing src elements that are http when we're viewing an https page * Typically this throws an insecure content violation in the browser. So we redirect them * to a local redirector which uses https and which redirects to the selected content * + * @param string $s * @returns string */ function sslify($s) { - if(strpos(z_root(),'https:') === false) + if (strpos(z_root(),'https:') === false) return $s; $matches = null; $cnt = preg_match_all("/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/",$s,$matches,PREG_SET_ORDER); - if($cnt) { - foreach($matches as $match) { - $filename = basename( parse_url($match[2],PHP_URL_PATH) ); + if ($cnt) { + foreach ($matches as $match) { + $filename = basename( parse_url($match[2], PHP_URL_PATH) ); $s = str_replace($match[2],z_root() . '/sslify/' . $filename . '?f=&url=' . urlencode($match[2]),$s); } } + return $s; } - function get_poke_verbs() { // index is present tense verb // value is array containing past tense verb, translation of present, translation of past @@ -1033,47 +1042,42 @@ function list_smilies() { $params = array('texts' => $texts, 'icons' => $icons); call_hooks('smilie', $params); + return $params; } /** - * - * Function: smilies - * - * Description: - * Replaces text emoticons with graphical images - * - * @Parameter: string $s - * - * Returns string + * @brief Replaces text emoticons with graphical images. * * It is expected that this function will be called using HTML text. * We will escape text between HTML pre and code blocks, and HTML attributes * (such as urls) from being processed. - * + * * At a higher level, the bbcode [nosmile] tag can be used to prevent this * function from being executed by the prepare_text() routine when preparing - * bbcode source for HTML display + * bbcode source for HTML display. * + * @param string $s + * @param boolean $sample (optional) default false + * @return string */ function smilies($s, $sample = false) { - if(intval(get_config('system','no_smilies')) - || (local_channel() && intval(get_pconfig(local_channel(),'system','no_smilies')))) + if(intval(get_config('system', 'no_smilies')) + || (local_channel() && intval(get_pconfig(local_channel(), 'system', 'no_smilies')))) return $s; - $s = preg_replace_callback('{<(pre|code)>.*?</\1>}ism','smile_shield',$s); - $s = preg_replace_callback('/<[a-z]+ .*?>/ism','smile_shield',$s); + $s = preg_replace_callback('{<(pre|code)>.*?</\1>}ism', 'smile_shield', $s); + $s = preg_replace_callback('/<[a-z]+ .*?>/ism', 'smile_shield', $s); $params = list_smilies(); $params['string'] = $s; - if($sample) { + if ($sample) { $s = '<div class="smiley-sample">'; - for($x = 0; $x < count($params['texts']); $x ++) { + for ($x = 0; $x < count($params['texts']); $x ++) { $s .= '<dl><dt>' . $params['texts'][$x] . '</dt><dd>' . $params['icons'][$x] . '</dd></dl>'; } - } - else { + } else { $params['string'] = preg_replace_callback('/<(3+)/','preg_heart',$params['string']); $s = str_replace($params['texts'],$params['icons'],$params['string']); } @@ -1083,6 +1087,12 @@ function smilies($s, $sample = false) { return $s; } +/** + * @brief + * + * @param array $m + * @return string + */ function smile_shield($m) { return '<!--base64:' . base64url_encode($m[0]) . '-->'; } @@ -1091,16 +1101,22 @@ function smile_unshield($m) { return base64url_decode($m[1]); } -// expand <3333 to the correct number of hearts - +/** + * @brief Expand <3333 to the correct number of hearts. + * + * @param array $x + */ function preg_heart($x) { $a = get_app(); - if(strlen($x[1]) == 1) + if (strlen($x[1]) == 1) return $x[0]; + $t = ''; for($cnt = 0; $cnt < strlen($x[1]); $cnt ++) $t .= '<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-heart.gif" alt="<3" />'; + $r = str_replace($x[0],$t,$x[0]); + return $r; } @@ -1118,27 +1134,33 @@ function day_translate($s) { return $ret; } - - +/** + * @brief normalises a string. + * + * @param string $url + * @return string + */ function normalise_link($url) { - $ret = str_replace(array('https:','//www.'), array('http:','//'), $url); - return(rtrim($ret,'/')); + $ret = str_replace(array('https:', '//www.'), array('http:', '//'), $url); + + return(rtrim($ret, '/')); } /** + * @brief Compare two URLs to see if they are the same. * - * Compare two URLs to see if they are the same, but ignore - * slight but hopefully insignificant differences such as if one - * is https and the other isn't, or if one is www.something and - * the other isn't - and also ignore case differences. + * But ignore slight but hopefully insignificant differences such as if one + * is https and the other isn't, or if one is www.something and the other + * isn't - and also ignore case differences. * - * Return true if the URLs match, otherwise false. + * @see normalis_link() * + * @param string $a + * @param string $b + * @return true if the URLs match, otherwise false */ - - -function link_compare($a,$b) { - if(strcasecmp(normalise_link($a),normalise_link($b)) === 0) +function link_compare($a, $b) { + if (strcasecmp(normalise_link($a), normalise_link($b)) === 0) return true; return false; @@ -1167,8 +1189,10 @@ function theme_attachments(&$item) { $icon = ''; $icontype = substr($r['type'],0,strpos($r['type'],'/')); - // FIXME This should probably be a giant "if" statement in the template so that we don't have icon names - // embedded in php code + /** + * @FIXME This should probably be a giant "if" statement in the + * template so that we don't have icon names embedded in php code. + */ switch($icontype) { case 'video': @@ -1394,11 +1418,14 @@ function prepare_body(&$item,$attach = false) { return $prep_arr['html']; } - -// Given a text string, convert from bbcode to html and add smilie icons. - - -function prepare_text($text,$content_type = 'text/bbcode') { +/** + * @brief Given a text string, convert from bbcode to html and add smilie icons. + * + * @param string $text + * @param sting $content_type + * @return string + */ +function prepare_text($text, $content_type = 'text/bbcode') { switch($content_type) { case 'text/plain': @@ -1451,19 +1478,21 @@ function prepare_text($text,$content_type = 'text/bbcode') { /** * zidify_callback() and zidify_links() work together to turn any HTML a tags with class="zrl" into zid links - * These will typically be generated by a bbcode '[zrl]' tag. This is done inside prepare_text() rather than bbcode() + * These will typically be generated by a bbcode '[zrl]' tag. This is done inside prepare_text() rather than bbcode() * 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. - * We assume it looks like <a class="zrl" href="xxxxxxxxxx"> and will not work if zrl and href appear in a different order. + * We assume it looks like \<a class="zrl" href="xxxxxxxxxx"\> and will not work if zrl and href appear in a different order. + * + * @param array $match + * @return string */ - - function zidify_callback($match) { $is_zid = ((feature_enabled(local_channel(),'sendzid')) || (strpos($match[1],'zrl')) ? true : false); $replace = '<a' . $match[1] . ' href="' . (($is_zid) ? zid($match[2]) : $match[2]) . '"'; $x = str_replace($match[0],$replace,$match[0]); + return $x; } @@ -1472,6 +1501,7 @@ function zidify_img_callback($match) { $replace = '<img' . $match[1] . ' src="' . (($is_zid) ? zid($match[2]) : $match[2]) . '"'; $x = str_replace($match[0],$replace,$match[0]); + return $x; } @@ -1479,16 +1509,17 @@ function zidify_img_callback($match) { function zidify_links($s) { $s = preg_replace_callback('/\<a(.*?)href\=\"(.*?)\"/ism','zidify_callback',$s); $s = preg_replace_callback('/\<img(.*?)src\=\"(.*?)\"/ism','zidify_img_callback',$s); + return $s; } - /** - * return atom link elements for all of our hubs + * @brief Return atom link elements for all of our hubs. + * + * @return string */ - function feed_hublinks() { - $hub = get_config('system','huburl'); + $hub = get_config('system', 'huburl'); $hubxml = ''; if(strlen($hub)) { @@ -1498,6 +1529,7 @@ function feed_hublinks() { $h = trim($h); if(! strlen($h)) continue; + $hubxml .= '<link rel="hub" href="' . xmlify($h) . '" />' . "\n" ; } } @@ -2094,15 +2126,16 @@ function extra_query_args() { } /** - * This function removes the tag $tag from the text $body and replaces it with - * the appropiate link. - * - * @param unknown_type $body the text to replace the tag in - * @param unknown_type $access_tag - used to return tag ACL exclusions e.g. @!foo - * @param unknown_type $str_tags string to add the tag to - * @param unknown_type $profile_uid - * @param unknown_type $tag the tag to replace + * @brief This function removes the tag $tag from the text $body and replaces it + * with the appropiate link. * + * @param App $a + * @param[in,out] string &$body the text to replace the tag in + * @param[in,out] string &$access_tag used to return tag ACL exclusions e.g. @!foo + * @param[in,out] string &$str_tags string to add the tag to + * @param int $profile_uid + * @param string $tag the tag to replace + * @param boolean $diaspora default false * @return boolean true if replaced, false if not replaced */ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $diaspora = false) { diff --git a/include/zot.php b/include/zot.php index 99a787cd9..28a2e8957 100644 --- a/include/zot.php +++ b/include/zot.php @@ -1,110 +1,113 @@ -<?php /** @file */ - -require_once('include/crypto.php'); -require_once('include/items.php'); -require_once('include/hubloc.php'); - +<?php /** - * Red implementation of zot protocol. + * @file include/zot.php + * @brief RedMatrix implementation of zot protocol. * * https://github.com/friendica/red/wiki/zot * https://github.com/friendica/red/wiki/Zot---A-High-Level-Overview * */ +require_once('include/crypto.php'); +require_once('include/items.php'); +require_once('include/hubloc.php'); + /** + * @brief Generates a unique string for use as a zot guid. * - * @function zot_new_uid($channel_nick) - * - * Generates a unique string for use as a zot guid using our DNS-based url, the channel nickname and some entropy. - * The entropy ensures uniqueness against re-installs where the same URL and nickname are chosen. - * NOTE: zot doesn't require this to be unique. Internally we use a whirlpool hash of this guid and the signature - * of this guid signed with the channel private key. This can be verified and should make the probability of - * collision of the verified result negligible within the constraints of our immediate universe. + * Generates a unique string for use as a zot guid using our DNS-based url, the + * channel nickname and some entropy. + * The entropy ensures uniqueness against re-installs where the same URL and + * nickname are chosen. * - * @param string channel_nickname = unique nickname of controlling entity + * @note zot doesn't require this to be unique. Internally we use a whirlpool + * hash of this guid and the signature of this guid signed with the channel + * private key. This can be verified and should make the probability of + * collision of the verified result negligible within the constraints of our + * immediate universe. * + * @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)); + return(base64url_encode(hash('whirlpool', $rawstr, true), true)); } - /** + * @brief Generates a portable hash identifier for a channel. * - * function make_xchan_hash($guid,$guid_sig) - * - * Generates a portable hash identifier for the channel identified by $guid and signed with $guid_sig - * This ID is portable across the network but MUST be calculated locally by verifying the signature - * and can not be trusted as an identity. + * Generates a portable hash identifier for the channel identified by $guid and + * signed with $guid_sig. + * This ID is portable across the network but MUST be calculated locally by + * verifying the signature and can not be trusted as an identity. * + * @param string $guid + * @param string $guid_sig */ - -function make_xchan_hash($guid,$guid_sig) { - return base64url_encode(hash('whirlpool',$guid . $guid_sig, true)); +function make_xchan_hash($guid, $guid_sig) { + return base64url_encode(hash('whirlpool', $guid . $guid_sig, true)); } /** - * @function zot_get_hublocs($hash) - * Given a zot hash, return all distinct hubs. - * This function is used in building the zot discovery packet - * and therefore should only be used by channels which are defined - * on this hub - * @param string $hash - xchan_hash - * @retuns array of hubloc (hub location structures) - * hubloc_id int - * hubloc_guid char(255) - * hubloc_guid_sig text - * hubloc_hash char(255) - * hubloc_addr char(255) - * hubloc_flags int - * hubloc_status int - * hubloc_url char(255) - * hubloc_url_sig text - * hubloc_host char(255) - * hubloc_callback char(255) - * hubloc_connect char(255) - * hubloc_sitekey text - * hubloc_updated datetime - * hubloc_connected datetime + * @brief Given a zot hash, return all distinct hubs. + * + * This function is used in building the zot discovery packet and therefore + * should only be used by channels which are defined on this hub. * + * @param string $hash - xchan_hash + * @returns array of hubloc (hub location structures) + * * \b hubloc_id int + * * \b hubloc_guid char(255) + * * \b hubloc_guid_sig text + * * \b hubloc_hash char(255) + * * \b hubloc_addr char(255) + * * \b hubloc_flags int + * * \b hubloc_status int + * * \b hubloc_url char(255) + * * \b hubloc_url_sig text + * * \b hubloc_host char(255) + * * \b hubloc_callback char(255) + * * \b hubloc_connect char(255) + * * \b hubloc_sitekey text + * * \b hubloc_updated datetime + * * \b hubloc_connected datetime */ - function zot_get_hublocs($hash) { - /** Only search for active hublocs - e.g. those that haven't been marked deleted */ + /* Only search for active hublocs - e.g. those that haven't been marked deleted */ $ret = q("select * from hubloc where hubloc_hash = '%s' and not ( hubloc_flags & %d )>0 order by hubloc_url ", dbesc($hash), intval(HUBLOC_FLAGS_DELETED) ); + return $ret; } /** + * @brief Builds a zot notification packet. * - * @function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null) - * builds a zot notification packet that you can either - * store in the queue with a message array or call zot_zot to immediately - * zot it to the other side - * - * @param array $channel => sender channel structure - * @param string $type => packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'force_refresh', 'notify', 'auth_check' - * @param array $recipients => envelope information, array ( 'guid' => string, 'guid_sig' => string ); empty for public posts - * @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 $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 + * Builds a zot notification packet that you can either store in the queue with + * a message array or call zot_zot to immediately zot it to the other side. * + * @param array $channel + * sender channel structure + * @param string $type + * packet type: one of 'ping', 'pickup', 'purge', 'refresh', 'force_refresh', 'notify', 'auth_check' + * @param array $recipients + * envelope information, array ( 'guid' => string, 'guid_sig' => string ); empty for public posts + * @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 $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 + * @param string $extra * @returns string json encoded zot packet */ - -function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_key = null, $secret = null, $extra = null) { +function zot_build_packet($channel, $type = 'notify', $recipients = null, $remote_key = null, $secret = null, $extra = null) { $data = array( 'type' => $type, @@ -118,84 +121,76 @@ function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_ 'version' => ZOT_REVISION ); - if($recipients) { - for($x = 0; $x < count($recipients); $x ++) + if ($recipients) { + for ($x = 0; $x < count($recipients); $x ++) unset($recipients[$x]['hash']); $data['recipients'] = $recipients; } - if($secret) { + if ($secret) { $data['secret'] = $secret; $data['secret_sig'] = base64url_encode(rsa_sign($secret,$channel['channel_prvkey'])); } - if($extra) { - foreach($extra as $k => $v) + if ($extra) { + foreach ($extra as $k => $v) $data[$k] = $v; } - logger('zot_build_packet: ' . print_r($data,true), LOGGER_DATA); // Hush-hush ultra top-secret mode - if($remote_key) { + if ($remote_key) { $data = crypto_encapsulate(json_encode($data),$remote_key); } return json_encode($data); } - /** - * @function: zot_zot - * @param: string $url - * @param: array $data + * @brief + * + * @see z_post_url() * - * @returns: array => see z_post_url for returned data format + * @param string $url + * @param array $data + * @return array see z_post_url() for returned data format */ - - - -function zot_zot($url,$data) { - return z_post_url($url,array('data' => $data)); +function zot_zot($url, $data) { + return z_post_url($url, array('data' => $data)); } /** - * @function: zot_finger + * @brief Look up information about channel. * - * Look up information about channel - * @param: string $webbie - * does not have to be host qualified e.g. 'foo' is treated as 'foo@thishub' - * @param: array $channel + * @param string $webbie + * does not have to be host qualified e.g. 'foo' is treated as 'foo\@thishub' + * @param array $channel * (optional), if supplied permissions will be enumerated specifically for $channel - * @param: boolean $autofallback + * @param boolean $autofallback * fallback/failover to http if https connection cannot be established. Default is true. * - * @returns: array => see z_post_url and mod/zfinger.php + * @return array see z_post_url() and \ref mod/zfinger.php */ +function zot_finger($webbie, $channel = null, $autofallback = true) { - -function zot_finger($webbie,$channel = null,$autofallback = true) { - - - if(strpos($webbie,'@') === false) { + if (strpos($webbie,'@') === false) { $address = $webbie; $host = get_app()->get_hostname(); - } - else { + } else { $address = substr($webbie,0,strpos($webbie,'@')); $host = substr($webbie,strpos($webbie,'@')+1); } $xchan_addr = $address . '@' . $host; - if((! $address) || (! $xchan_addr)) { + if ((! $address) || (! $xchan_addr)) { logger('zot_finger: no address :' . $webbie); return array('success' => false); - } + } logger('using xchan_addr: ' . $xchan_addr, LOGGER_DATA); - + // potential issue here; the xchan_addr points to the primary hub. // The webbie we were called with may not, so it might not be found // unless we query for hubloc_addr instead of xchan_addr @@ -207,26 +202,24 @@ function zot_finger($webbie,$channel = null,$autofallback = true) { intval(HUBLOC_FLAGS_PRIMARY) ); - if($r) { + if ($r) { $url = $r[0]['hubloc_url']; - if($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') { + if ($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') { logger('zot_finger: alternate network: ' . $webbie); logger('url: '.$url.', net: '.var_export($r[0]['hubloc_network'],true), LOGGER_DATA); return array('success' => false); - } - } - else { + } + } else { $url = 'https://' . $host; } - $rhs = '/.well-known/zot-info'; $https = ((strpos($url,'https://') === 0) ? true : false); logger('zot_finger: ' . $address . ' at ' . $url, LOGGER_DEBUG); - if($channel) { + if ($channel) { $postvars = array( 'address' => $address, 'target' => $channel['channel_guid'], @@ -236,88 +229,85 @@ function zot_finger($webbie,$channel = null,$autofallback = true) { $result = z_post_url($url . $rhs,$postvars); - - if((! $result['success']) && ($autofallback)) { - if($https) { + if ((! $result['success']) && ($autofallback)) { + if ($https) { logger('zot_finger: https failed. falling back to http'); $result = z_post_url('http://' . $host . $rhs,$postvars); } } - } - else { + } else { $rhs .= '?f=&address=' . urlencode($address); $result = z_fetch_url($url . $rhs); - if((! $result['success']) && ($autofallback)) { - if($https) { + if ((! $result['success']) && ($autofallback)) { + if ($https) { logger('zot_finger: https failed. falling back to http'); $result = z_fetch_url('http://' . $host . $rhs); } } } - - if(! $result['success']) - logger('zot_finger: no results'); - return $result; + if (! $result['success']) + logger('zot_finger: no results'); + return $result; } /** - * @function: zot_refresh($them, $channel = null, $force = false) + * @brief Refreshes after permission changed or friending, etc. + * + * zot_refresh is typically invoked when somebody has changed permissions of a channel and they are notified + * to fetch new permissions via a finger/discovery operation. This may result in a new connection + * (abook entry) being added to a local channel and it may result in auto-permissions being granted. + * + * Friending in zot is accomplished by sending a refresh packet to a specific channel which indicates a + * permission change has been made by the sender which affects the target channel. The hub controlling + * the target channel does targetted discovery (a zot-finger request requesting permissions for the local + * channel). These are decoded here, and if necessary and abook structure (addressbook) is created to store + * the permissions assigned to this channel. + * + * Initially these abook structures are created with a 'pending' flag, so that no reverse permissions are + * implied until this is approved by the owner channel. A channel can also auto-populate permissions in + * return and send back a refresh packet of its own. This is used by forum and group communication channels + * so that friending and membership in the channel's "club" is automatic. * - * zot_refresh is typically invoked when somebody has changed permissions of a channel and they are notified - * to fetch new permissions via a finger/discovery operation. This may result in a new connection - * (abook entry) being added to a local channel and it may result in auto-permissions being granted. - * - * Friending in zot is accomplished by sending a refresh packet to a specific channel which indicates a - * permission change has been made by the sender which affects the target channel. The hub controlling - * the target channel does targetted discovery (a zot-finger request requesting permissions for the local - * channel). These are decoded here, and if necessary and abook structure (addressbook) is created to store - * the permissions assigned to this channel. - * - * Initially these abook structures are created with a 'pending' flag, so that no reverse permissions are - * implied until this is approved by the owner channel. A channel can also auto-populate permissions in - * return and send back a refresh packet of its own. This is used by forum and group communication channels - * so that friending and membership in the channel's "club" is automatic. - * * @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 * - * @returns boolean true if successful, else false + * @returns boolean true if successful, else false */ +function zot_refresh($them, $channel = null, $force = false) { -function zot_refresh($them,$channel = null, $force = false) { - - if(array_key_exists('xchan_network',$them) && ($them['xchan_network'] !== 'zot')) { + if (array_key_exists('xchan_network', $them) && ($them['xchan_network'] !== 'zot')) { logger('zot_refresh: not got zot. ' . $them['xchan_name']); return true; } logger('zot_refresh: them: ' . print_r($them,true), LOGGER_DATA); - if($channel) + if ($channel) logger('zot_refresh: channel: ' . print_r($channel,true), LOGGER_DATA); $url = null; - if($them['hubloc_url']) + if ($them['hubloc_url']) { $url = $them['hubloc_url']; - else { + } else { $r = q("select hubloc_url, hubloc_flags from hubloc where hubloc_hash = '%s'", dbesc($them['xchan_hash']) ); - if($r) { - foreach($r as $rr) { - if($rr['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) { + if ($r) { + foreach ($r as $rr) { + if ($rr['hubloc_flags'] & HUBLOC_FLAGS_PRIMARY) { $url = $rr['hubloc_url']; break; } } - if(! $url) + if (! $url) $url = $r[0]['hubloc_url']; } } - if(! $url) { + if (! $url) { logger('zot_refresh: no url'); return false; } @@ -330,12 +320,13 @@ function zot_refresh($them,$channel = null, $force = false) { $postvars['key'] = $channel['channel_pubkey']; } - if(array_key_exists('xchan_addr',$them) && $them['xchan_addr']) + if (array_key_exists('xchan_addr',$them) && $them['xchan_addr']) $postvars['address'] = $them['xchan_addr']; - if(array_key_exists('xchan_hash',$them) && $them['xchan_hash']) + if (array_key_exists('xchan_hash',$them) && $them['xchan_hash']) $postvars['guid_hash'] = $them['xchan_hash']; - if(array_key_exists('xchan_guid',$them) && $them['xchan_guid'] + if (array_key_exists('xchan_guid',$them) && $them['xchan_guid'] && array_key_exists('xchan_guid_sig',$them) && $them['xchan_guid_sig']) { + $postvars['guid'] = $them['xchan_guid']; $postvars['guid_sig'] = $them['xchan_guid_sig']; } @@ -343,19 +334,19 @@ function zot_refresh($them,$channel = null, $force = false) { $rhs = '/.well-known/zot-info'; $result = z_post_url($url . $rhs,$postvars); - + logger('zot_refresh: zot-info: ' . print_r($result,true), LOGGER_DATA); - if($result['success']) { + if ($result['success']) { $j = json_decode($result['body'],true); - if(! (($j) && ($j['success']))) { + if (! (($j) && ($j['success']))) { logger('zot_refresh: result not decodable'); return false; } - $x = import_xchan($j,(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED)); + $x = import_xchan($j, (($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED)); if(! $x['success']) return false; @@ -415,7 +406,7 @@ function zot_refresh($them,$channel = null, $force = false) { $next_birthday = $r[0]['abook_dob']; $current_abook_connected = (($r[0]['abook_flags'] & ABOOK_FLAG_UNCONNECTED) ? 0 : 1); - + $y = q("update abook set abook_their_perms = %d, abook_dob = '%s' where abook_xchan = '%s' and abook_channel = %d and not (abook_flags & %d) > 0 ", @@ -430,8 +421,8 @@ function zot_refresh($them,$channel = null, $force = false) { // if they are in your address book but you aren't in theirs, and/or this does not // match your current connected state setting, toggle it. - // FIXME: uncoverted to postgres - // FIXME: when this was enabled, all contacts became unconnected. Currently disabled intentionally + /** @FIXME uncoverted to postgres */ + /** @FIXME when this was enabled, all contacts became unconnected. Currently disabled intentionally */ // $y1 = q("update abook set abook_flags = (abook_flags ^ %d) // where abook_xchan = '%s' and abook_channel = %d // and not (abook_flags & %d) limit 1", @@ -505,7 +496,7 @@ function zot_refresh($them,$channel = null, $force = false) { 'type' => NOTIFY_INTRO, 'from_xchan' => $x['hash'], 'to_xchan' => $channel['channel_hash'], - 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'], + 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'], )); } @@ -514,7 +505,6 @@ function zot_refresh($them,$channel = null, $force = false) { || (! ($new_connection[0]['abook_flags'] & ABOOK_FLAG_PENDING)) ) proc_run('php','include/onepoll.php',$new_connection[0]['abook_id']); } - } } } @@ -524,25 +514,22 @@ function zot_refresh($them,$channel = null, $force = false) { } /** - * @function: zot_gethub + * @brief Look up if channel is known and previously verified. * - * A guid and a url, both signed by the sender, distinguish a known sender at a known location - * This function looks these up to see if the channel is known and therefore previously verified. - * If not, we will need to verify it. + * A guid and a url, both signed by the sender, distinguish a known sender at a + * known location. + * This function looks these up to see if the channel is known and therefore + * previously verified. If not, we will need to verify it. * - * @param array $arr - * $arr must contain: - * string $arr['guid'] => guid of conversant - * string $arr['guid_sig'] => guid signed with conversant's private key - * string $arr['url'] => URL of the origination hub of this communication - * string $arr['url_sig'] => URL signed with conversant's private key - * + * @param array $arr an assoziative array which must contain: + * * \e string \b guid => guid of conversant + * * \e string \b guid_sig => guid signed with conversant's private key + * * \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 => hubloc record + * @returns array|null null if site is blacklisted or not found, otherwise an + * array with an hubloc record */ - - - function zot_gethub($arr) { if($arr['guid'] && $arr['guid_sig'] && $arr['url'] && $arr['url_sig']) { @@ -581,26 +568,23 @@ function zot_gethub($arr) { } /** - * @function zot_register_hub($arr) + * @brief Registers an unknown hup. * - * A communication has been received which has an unknown (to us) sender. - * Perform discovery based on our calculated hash of the sender at the origination address. - * This will fetch the discovery packet of the sender, which contains the public key we - * need to verify our guid and url signatures. + * A communication has been received which has an unknown (to us) sender. + * Perform discovery based on our calculated hash of the sender at the + * origination address. This will fetch the discovery packet of the sender, + * which contains the public key we need to verify our guid and url signatures. * - * @param array $arr - * $arr must contain: - * string $arr['guid'] => guid of conversant - * string $arr['guid_sig'] => guid signed with conversant's private key - * string $arr['url'] => URL of the origination hub of this communication - * string $arr['url_sig'] => URL signed with conversant's private key - * + * @param array $arr an assoziative array which must contain: + * * \e string \b guid => guid of conversant + * * \e string \b guid_sig => guid signed with conversant's private key + * * \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 => 'success' (boolean true or false) - * 'message' (optional error string only if success is false) + * @returns array an assoziative array with: + * * \b success boolean true or false + * * \b message (optional) error string only if success is false */ - - function zot_register_hub($arr) { $result = array('success' => false); @@ -640,15 +624,14 @@ function zot_register_hub($arr) { } } } + return $result; } - /** - * @function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED) - * Takes an associative array of a fetched discovery packet and updates + * @brief Takes an associative array of a fetched discovery packet and updates * all internal data structures which need to be updated as a result. - * + * * @param array $arr => json_decoded discovery packet * @param int $ud_flags * Determines whether to create a directory update record if any changes occur, default is UPDATE_FLAGS_UPDATED @@ -659,13 +642,12 @@ 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. * - * @returns array => 'success' (boolean true or false) - * 'message' (optional error string only if success is false) + * @return associative array + * * \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) { - call_hooks('import_xchan', $arr); $ret = array('success' => false); @@ -700,11 +682,11 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $r = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($xchan_hash) - ); + ); if(! array_key_exists('connect_url', $arr)) - $arr['connect_url'] = ''; - + $arr['connect_url'] = ''; + if(strpos($arr['address'],'/') !== false) $arr['address'] = substr($arr['address'],0,strpos($arr['address'],'/')); @@ -713,14 +695,13 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $import_photos = true; // if we import an entry from a site that's not ours and either or both of us is off the grid - hide the entry. - // TODO: check if we're the same directory realm, which would mean we are allowed to see it + /** @TODO: check if we're the same directory realm, which would mean we are allowed to see it */ $dirmode = get_config('system','directory_mode'); if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) && ($arr['site']['url'] != z_root())) $arr['searchable'] = false; - $hidden = (1 - intval($arr['searchable'])); // Be careful - XCHAN_FLAGS_HIDDEN should evaluate to 1 @@ -770,11 +751,9 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $what .= 'xchan '; $changed = true; } - } - else { + } else { $import_photos = true; - if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) && ($arr['site']['url'] != z_root())) $arr['searchable'] = false; @@ -789,7 +768,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $new_flags |= XCHAN_FLAGS_SELFCENSORED; if(array_key_exists('deleted',$arr) && $arr['deleted']) $new_flags |= XCHAN_FLAGS_DELETED; - + $x = q("insert into xchan ( xchan_hash, xchan_guid, xchan_guid_sig, xchan_pubkey, xchan_photo_mimetype, xchan_photo_l, xchan_addr, xchan_url, xchan_connurl, xchan_follow, xchan_connpage, xchan_name, xchan_network, xchan_photo_date, xchan_name_date, xchan_flags) values ( '%s', '%s', '%s', '%s' , '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d) ", @@ -813,11 +792,9 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $what .= 'new_xchan'; $changed = true; + } - } - - - if($import_photos) { + if ($import_photos) { require_once('include/photo/photo_driver.php'); @@ -826,9 +803,9 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1", dbesc($xchan_hash) ); - if($local) { - $ph = z_fetch_url($arr['photo'],true); - if($ph['success']) { + if ($local) { + $ph = z_fetch_url($arr['photo'], true); + if ($ph['success']) { import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'],$local[0]['channel_id']); // reset the names in case they got messed up when we had a bug in this function $photos = array( @@ -839,12 +816,11 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { false ); } + } else { + $photos = import_profile_photo($arr['photo'], $xchan_hash); } - else { - $photos = import_profile_photo($arr['photo'],$xchan_hash); - } - if($photos) { - if($photos[4]) { + if ($photos) { + if ($photos[4]) { // importing the photo failed somehow. Leave the photo_date alone so we can try again at a later date. // This often happens when somebody joins the matrix with a bad cert. $r = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' @@ -855,8 +831,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { dbesc($photos[3]), dbesc($xchan_hash) ); - } - else { + } else { $r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'", dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])), @@ -875,8 +850,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { // what we are missing for true hub independence is for any changes in the primary hub to // get reflected not only in the hublocs, but also to update the URLs and addr in the appropriate xchan - - $s = sync_locations($arr,$arr); + $s = sync_locations($arr, $arr); if($s) { if($s['change_message']) @@ -915,8 +889,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $what .= 'profile '; $changed = true; } - } - else { + } else { logger('import_xchan: profile not available - hiding'); // they may have made it private $r = q("delete from xprof where xprof_hash = '%s'", @@ -935,7 +908,6 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $changed = true; } } - if(($changed) || ($ud_flags == UPDATE_FLAGS_FORCED)) { $guid = random_string() . '@' . get_app()->get_hostname(); @@ -956,60 +928,52 @@ 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); return $ret; } /** - * @function zot_process_response($hub,$arr,$outq) { - * Called immediately after sending a zot message which is using queue processing - * Updates the queue item according to the response result and logs any information - * returned to aid communications troubleshooting. + * @brief Called immediately after sending a zot message which is using queue processing. + * + * Updates the queue item according to the response result and logs any information + * returned to aid communications troubleshooting. * * @param string $hub - url of site we just contacted * @param array $arr - output of z_post_url() * @param array $outq - The queue structure attached to this request - * - * @returns nothing */ +function zot_process_response($hub, $arr, $outq) { - -function zot_process_response($hub,$arr,$outq) { - - if(! $arr['success']) { + if (! $arr['success']) { logger('zot_process_response: failed: ' . $hub); return; } - $x = json_decode($arr['body'],true); + $x = json_decode($arr['body'], true); - if(! $x) { + if (! $x) { logger('zot_process_response: No json from ' . $hub); logger('zot_process_response: headers: ' . print_r($arr['header'],true), LOGGER_DATA); } // update the timestamp for this site - $r = q("update site set site_update = '%s' where site_url = '%s'", + q("update site set site_update = '%s' where site_url = '%s'", dbesc(datetime_convert()), dbesc(dirname($hub)) ); - // synchronous message types are handled immediately // async messages remain in the queue until processed. - if(intval($outq['outq_async'])) { - $r = q("update outq set outq_delivered = 1, outq_updated = '%s' where outq_hash = '%s' and outq_channel = %d", + if (intval($outq['outq_async'])) { + q("update outq set outq_delivered = 1, outq_updated = '%s' where outq_hash = '%s' and outq_channel = %d", dbesc(datetime_convert()), dbesc($outq['outq_hash']), intval($outq['outq_channel']) ); - } - else { - $r = q("delete from outq where outq_hash = '%s' and outq_channel = %d", + } else { + q("delete from outq where outq_hash = '%s' and outq_channel = %d", dbesc($outq['outq_hash']), intval($outq['outq_channel']) ); @@ -1019,19 +983,20 @@ function zot_process_response($hub,$arr,$outq) { } /** - * @function zot_fetch($arr) + * @brief + * + * We received a notification packet (in mod/post.php) that a message is waiting for us, and we've verified the sender. + * Now send back a pickup message, using our message tracking ID ($arr['secret']), which we will sign with our site private key. + * The entire pickup message is encrypted with the remote site's public key. + * If everything checks out on the remote end, we will receive back a packet containing one or more messages, + * which will be processed and delivered before this function ultimately returns. + * + * @see zot_import() * - * We received a notification packet (in mod/post.php) that a message is waiting for us, and we've verified the sender. - * Now send back a pickup message, using our message tracking ID ($arr['secret']), which we will sign with our site private key. - * The entire pickup message is encrypted with the remote site's public key. - * If everything checks out on the remote end, we will receive back a packet containing one or more messages, - * which will be processed and delivered before this function ultimately returns. - * * @param array $arr * 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); @@ -1054,31 +1019,36 @@ function zot_fetch($arr) { ); $datatosend = json_encode(crypto_encapsulate(json_encode($data),$ret_hub['hubloc_sitekey'])); - + $fetch = zot_zot($url,$datatosend); $result = zot_import($fetch, $arr['sender']['url']); + return $result; } /** - * @function zot_import + * @brief Process incoming array of messages. * * Process an incoming array of messages which were obtained via pickup, and * import, update, delete as directed. - * - * @param array $arr => 'pickup' structure returned from remote site - * @param string $sender_url => the url specified by the sender in the initial communication - * we will verify the sender and url in each returned message structure and also verify - * that all the messages returned match the site url that we are currently processing. - * - * The message types handled here are 'activity' (e.g. posts), 'mail' , 'profile', 'location', - * and 'channel_sync' - * - * @returns array => array ( [0] => string $channel_hash, [1] => string $delivery_status, [2] => string $address ) - * suitable for logging remotely, enumerating the processing results of each message/recipient combination. - * + * + * The message types handled here are 'activity' (e.g. posts), 'mail' , + * 'profile', 'location' and 'channel_sync'. + * + * @param array $arr + * 'pickup' structure returned from remote site + * @param string $sender_url + * the url specified by the sender in the initial communication. + * We will verify the sender and url in each returned message structure and + * also verify that all the messages returned match the site url that we are + * 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 */ - function zot_import($arr, $sender_url) { $data = json_decode($arr['body'],true); @@ -1168,7 +1138,7 @@ function zot_import($arr, $sender_url) { } } - logger('public post'); + logger('public post'); // Public post. look for any site members who are or may be accepting posts from this sender // and who are allowed to see them based on the sender's permissions @@ -1190,7 +1160,6 @@ function zot_import($arr, $sender_url) { $i['message']['flags'] = array(); if(! in_array('private',$i['message']['flags'])) $i['message']['flags'][] = 'private'; - } } @@ -1215,8 +1184,8 @@ function zot_import($arr, $sender_url) { logger('zot_import: no deliveries on this site'); continue; } - - if($i['message']) { + + if($i['message']) { if($i['message']['type'] === 'activity') { $arr = get_item_elements($i['message']); @@ -1230,7 +1199,6 @@ function zot_import($arr, $sender_url) { $relay = ((array_key_exists('flags',$i['message']) && in_array('relay',$i['message']['flags'])) ? true : false); $result = process_delivery($i['notify']['sender'],$arr,$deliveries,$relay,false,$message_request); - } elseif($i['message']['type'] === 'mail') { $arr = get_mail_elements($i['message']); @@ -1238,9 +1206,7 @@ function zot_import($arr, $sender_url) { logger('Mail received: ' . print_r($arr,true), LOGGER_DATA); logger('Mail recipients: ' . print_r($deliveries,true), LOGGER_DATA); - $result = process_mail_delivery($i['notify']['sender'],$arr,$deliveries); - } elseif($i['message']['type'] === 'profile') { $arr = get_profile_elements($i['message']); @@ -1249,9 +1215,7 @@ function zot_import($arr, $sender_url) { logger('Profile recipients: ' . print_r($deliveries,true), LOGGER_DATA); $result = process_profile_delivery($i['notify']['sender'],$arr,$deliveries); - } - elseif($i['message']['type'] === 'channel_sync') { // $arr = get_channelsync_elements($i['message']); @@ -1270,31 +1234,34 @@ function zot_import($arr, $sender_url) { $result = process_location_delivery($i['notify']['sender'],$arr,$deliveries); } - } if($result){ - $return = array_merge($return,$result); + $return = array_merge($return, $result); } } } return $return; - } // A public message with no listed recipients can be delivered to anybody who -// has PERMS_NETWORK for that type of post, PERMS_AUTHED (in-network senders are +// has PERMS_NETWORK for that type of post, PERMS_AUTHED (in-network senders are // by definition authenticated) or PERMS_SITE and is one the same // site, or PERMS_SPECIFIC and the sender is a contact who is granted // permissions via their connection permissions in the address book. // Here we take a given message and construct a list of hashes of everybody -// on the site that we should try and deliver to. +// on the site that we should try and deliver to. // Some of these will be rejected, but this gives us a place to start. +/** + * @brief + * + * @param array $msg + * @return NULL|array + */ function public_recips($msg) { - require_once('include/identity.php'); $check_mentions = false; @@ -1363,7 +1330,6 @@ function public_recips($msg) { or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0 or ( " . $col . " & " . intval(PERMS_AUTHED) . ") > 0 ) "; - $r = q("select channel_hash as hash from channel $sql or channel_hash = '%s' and ( channel_pageflags & " . intval(PAGE_REMOVED) . " ) = 0 ", dbesc($msg['notify']['sender']['hash']) @@ -1514,7 +1480,6 @@ function allowed_public_recips($msg) { return $results; } - return array(); } @@ -1544,7 +1509,6 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque continue; } - $channel = $r[0]; // allow public postings to the sys channel regardless of permissions, but not @@ -1763,7 +1727,6 @@ function remove_community_tag($sender,$arr,$uid) { return; logger('remove_community_tag: invoked'); - if(! get_pconfig($uid,'system','blocktags')) { logger('remove_community tag: permission denied.'); @@ -1806,8 +1769,8 @@ function remove_community_tag($sender,$arr,$uid) { logger('remove_community_tag: no parent message'); return; } - - $x = q("delete from term where uid = %d and oid = %d and otype = %d and type = %d and term = '%s' and url = '%s'", + + q("delete from term where uid = %d and oid = %d and otype = %d and type = %d and term = '%s' and url = '%s'", intval($uid), intval($r[0]['id']), intval(TERM_OBJ_POST), @@ -1815,8 +1778,6 @@ function remove_community_tag($sender,$arr,$uid) { dbesc($i['object']['title']), dbesc(get_rel_link($i['object']['link'],'alternate')) ); - - return; } function update_imported_item($sender,$item,$uid) { @@ -1826,12 +1787,20 @@ function update_imported_item($sender,$item,$uid) { logger('update_imported_item: failed: ' . $x['message']); else logger('update_imported_item'); - } -function delete_imported_item($sender,$item,$uid,$relay) { +/** + * @brief Deletes an imported item. + * + * @param array $sender + * @param array $item + * @param int $uid + * @param unknown $relay + * @return boolean|int post_id + */ +function delete_imported_item($sender, $item, $uid, $relay) { - logger('delete_imported_item invoked',LOGGER_DEBUG); + logger('delete_imported_item invoked', LOGGER_DEBUG); $ownership_valid = false; $item_found = false; @@ -1841,13 +1810,13 @@ function delete_imported_item($sender,$item,$uid,$relay) { dbesc($item['mid']), intval($uid) ); - if($r) { - if($r[0]['author_xchan'] === $sender['hash'] || $r[0]['owner_xchan'] === $sender['hash'] || $r[0]['source_xchan'] === $sender['hash']) + if ($r) { + if ($r[0]['author_xchan'] === $sender['hash'] || $r[0]['owner_xchan'] === $sender['hash'] || $r[0]['source_xchan'] === $sender['hash']) $ownership_valid = true; + $post_id = $r[0]['id']; $item_found = true; - } - else { + } else { // perhaps the item is still in transit and the delete notification got here before the actual item did. Store it with the deleted flag set. // item_store() won't try to deliver any notifications or start delivery chains if this flag is set. @@ -1855,22 +1824,24 @@ function delete_imported_item($sender,$item,$uid,$relay) { // But this will ensure that if the (undeleted) original post comes in at a later date, we'll reject it because it will have an older timestamp. logger('delete received for non-existent item - storing item data.'); - if($arr['author_xchan'] === $sender['hash'] || $arr['owner_xchan'] === $sender['hash'] || $arr['source_xchan'] === $sender['hash']) { + + /** @BUG $arr is undefined here, so this is dead code */ + if ($arr['author_xchan'] === $sender['hash'] || $arr['owner_xchan'] === $sender['hash'] || $arr['source_xchan'] === $sender['hash']) { $ownership_valid = true; $item_result = item_store($arr); $post_id = $item_result['item_id']; } } - if($ownership_valid == false) { + if ($ownership_valid === false) { logger('delete_imported_item: failed: ownership issue'); return false; } - if($item_found) { - if($r[0]['item_restrict'] & ITEM_DELETED) { + if ($item_found) { + if ($r[0]['item_restrict'] & ITEM_DELETED) { logger('delete_imported_item: item was already deleted'); - if(! $relay) + if (! $relay) return false; // This is a bit hackish, but may have to suffice until the notification/delivery loop is optimised @@ -1879,9 +1850,9 @@ function delete_imported_item($sender,$item,$uid,$relay) { // code path downstream can relay it again (causing a loop). Since it's already gone it's not coming // back, and we aren't going to (or shouldn't at any rate) delete it again in the future - so losing // this information from the metadata should have no other discernible impact. - - if(($r[0]['id'] != $r[0]['parent']) && ($r[0]['item_flags'] & ITEM_ORIGIN)) { - $x = q("update item set item_flags = %d where id = %d and uid = %d", + + if (($r[0]['id'] != $r[0]['parent']) && ($r[0]['item_flags'] & ITEM_ORIGIN)) { + q("update item set item_flags = %d where id = %d and uid = %d", intval($r[0]['item_flags'] ^ ITEM_ORIGIN), intval($r[0]['id']), intval($r[0]['uid']) @@ -1889,14 +1860,13 @@ function delete_imported_item($sender,$item,$uid,$relay) { } } - require_once('include/items.php'); // Use phased deletion to set the deleted flag, call both tag_deliver and the notifier to notify downstream channels // and then clean up after ourselves with a cron job after several days to do the delete_item_lowlevel() (DROPITEM_PHASE2). - drop_item($post_id,false, DROPITEM_PHASE1); - tag_deliver($uid,$post_id); + drop_item($post_id, false, DROPITEM_PHASE1); + tag_deliver($uid, $post_id); } return $post_id; @@ -1904,17 +1874,13 @@ function delete_imported_item($sender,$item,$uid,$relay) { function process_mail_delivery($sender,$arr,$deliveries) { - $result = array(); - if($sender['hash'] != $arr['from_xchan']) { logger('process_mail_delivery: sender is not mail author'); return; } - - foreach($deliveries as $d) { $r = q("select * from channel where channel_hash = '%s' limit 1", dbesc($d['hash']) @@ -1946,7 +1912,7 @@ function process_mail_delivery($sender,$arr,$deliveries) { $result[] = array($d['hash'],'mail recalled',$channel['channel_name'],$arr['mid']); logger('mail_recalled'); } - else { + else { $result[] = array($d['hash'],'duplicate mail received',$channel['channel_name'],$arr['mid']); logger('duplicate mail received'); } @@ -1974,7 +1940,6 @@ function process_rating_delivery($sender,$arr) { dbesc($sender['hash']) ); - if((! $z) || (! rsa_verify($arr['target'] . '.' . $arr['rating'] . '.' . $arr['rating_text'], base64url_decode($arr['signature']),$z[0]['xchan_pubkey']))) { logger('failed to verify rating'); return; @@ -2012,7 +1977,6 @@ function process_rating_delivery($sender,$arr) { ); logger('rating created'); } - return; } @@ -2080,7 +2044,6 @@ function sync_locations($sender,$arr,$absolute = false) { continue; } - for($x = 0; $x < count($xisting); $x ++) { if(($xisting[$x]['hubloc_url'] === $location['url']) && ($xisting[$x]['hubloc_sitekey'] === $location['sitekey'])) { @@ -2250,7 +2213,7 @@ function sync_locations($sender,$arr,$absolute = false) { ); if($r) hubloc_change_primary($r[0]); - } + } } // get rid of any hubs we have for this channel which weren't reported. @@ -2275,17 +2238,23 @@ function sync_locations($sender,$arr,$absolute = false) { $ret['changed'] = $changed; return $ret; - } - +/** + * @brief Returns an array with all known distinct hubs for this channel. + * + * @see zot_get_hublocs() + * @param array $channel an assoziative array which must contain + * * \e string \b channel_hash the hash of the channel + * @return array an array with assoziated arrays + */ function zot_encode_locations($channel) { $ret = array(); $x = zot_get_hublocs($channel['channel_hash']); - if($x && count($x)) { - foreach($x as $hub) { - if(! ($hub['hubloc_flags'] & HUBLOC_FLAGS_UNVERIFIED)) { + if ($x && count($x)) { + foreach ($x as $hub) { + if (! ($hub['hubloc_flags'] & HUBLOC_FLAGS_UNVERIFIED)) { $ret[] = array( 'host' => $hub['hubloc_host'], 'address' => $hub['hubloc_addr'], @@ -2299,24 +2268,25 @@ function zot_encode_locations($channel) { } } } + return $ret; } - - - -/* - * @function import_directory_profile +/** + * @brief Imports a directory profile. * - * @returns boolean $updated if something changed - * + * @param string $hash + * @param array $profile + * @param string $addr + * @param number $ud_flags + * @param number $suppress_update default 0 + * @return boolean $updated if something changed */ - -function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) { +function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) { logger('import_directory_profile', LOGGER_DEBUG); - if(! $hash) + if (! $hash) return false; $arr = array(); @@ -2337,11 +2307,11 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_ $arr['xprof_hometown'] = (($profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : ''); $clean = array(); - if(array_key_exists('keywords',$profile) and is_array($profile['keywords'])) { + if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) { import_directory_keywords($hash,$profile['keywords']); - foreach($profile['keywords'] as $kw) { - $kw = trim(htmlspecialchars($kw,ENT_COMPAT,'UTF-8',false)); - $kw = trim($kw,','); + foreach ($profile['keywords'] as $kw) { + $kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false)); + $kw = trim($kw, ','); $clean[] = $kw; } } @@ -2352,48 +2322,47 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_ // These are not translated, so the German "erwachsenen" keyword will not censor the directory profile. Only the English form - "adult". - if(in_arrayi('nsfw',$clean) || in_arrayi('adult',$clean)) { + if (in_arrayi('nsfw', $clean) || in_arrayi('adult', $clean)) { q("update xchan set xchan_flags = (xchan_flags | %d) where xchan_hash = '%s'", intval(XCHAN_FLAGS_SELFCENSORED), dbesc($hash) ); } - $r = q("select * from xprof where xprof_hash = '%s' limit 1", dbesc($hash) ); - - if($arr['xprof_age'] > 150) + + if ($arr['xprof_age'] > 150) $arr['xprof_age'] = 150; - if($arr['xprof_age'] < 0) + if ($arr['xprof_age'] < 0) $arr['xprof_age'] = 0; - - if($r) { + + if ($r) { $update = false; - foreach($r[0] as $k => $v) { - if((array_key_exists($k,$arr)) && ($arr[$k] != $v)) { + foreach ($r[0] as $k => $v) { + if ((array_key_exists($k,$arr)) && ($arr[$k] != $v)) { logger('import_directory_profile: update ' . $k . ' => ' . $arr[$k]); $update = true; break; } } - if($update) { - $x = q("update xprof set + if ($update) { + q("update xprof set xprof_desc = '%s', xprof_dob = '%s', - xprof_age = %d, + xprof_age = %d, xprof_gender = '%s', xprof_marital = '%s', xprof_sexual = '%s', xprof_locale = '%s', xprof_region = '%s', xprof_postcode = '%s', - xprof_country = '%s', - xprof_about = '%s', - xprof_homepage = '%s', - xprof_hometown = '%s', - xprof_keywords = '%s' + xprof_country = '%s', + xprof_about = '%s', + xprof_homepage = '%s', + xprof_hometown = '%s', + xprof_keywords = '%s' where xprof_hash = '%s'", dbesc($arr['xprof_desc']), dbesc($arr['xprof_dob']), @@ -2412,11 +2381,10 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_ dbesc($arr['xprof_hash']) ); } - } - else { + } else { $update = true; logger('import_directory_profile: new profile '); - $x = 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') ", + 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']), dbesc($arr['xprof_dob']), @@ -2438,8 +2406,9 @@ function import_directory_profile($hash,$profile,$addr,$ud_flags = UPDATE_FLAGS_ $d = array('xprof' => $arr, 'profile' => $profile, 'update' => $update); call_hooks('import_directory_profile', $d); - if(($d['update']) && (! $suppress_update)) + if (($d['update']) && (! $suppress_update)) update_modtime($arr['xprof_hash'],random_string() . '@' . get_app()->get_hostname(), $addr, $ud_flags); + return $d['update']; } @@ -2528,7 +2497,6 @@ function import_site($arr,$pubkey) { $site_directory = 0; if($arr['directory_mode'] == 'normal') $site_directory = DIRECTORY_MODE_NORMAL; - if($arr['directory_mode'] == 'primary') $site_directory = DIRECTORY_MODE_PRIMARY; if($arr['directory_mode'] == 'secondary') @@ -2536,9 +2504,6 @@ function import_site($arr,$pubkey) { if($arr['directory_mode'] == 'standalone') $site_directory = DIRECTORY_MODE_STANDALONE; - - - $register_policy = 0; if($arr['register_policy'] == 'closed') $register_policy = REGISTER_CLOSED; @@ -2569,16 +2534,16 @@ function import_site($arr,$pubkey) { if(! $x['success']) $access_policy = ACCESS_PRIVATE; } - + $directory_url = htmlspecialchars($arr['directory_url'],ENT_COMPAT,'UTF-8',false); $url = htmlspecialchars(strtolower($arr['url']),ENT_COMPAT,'UTF-8',false); $sellpage = htmlspecialchars($arr['sellpage'],ENT_COMPAT,'UTF-8',false); $site_location = htmlspecialchars($arr['location'],ENT_COMPAT,'UTF-8',false); $site_realm = htmlspecialchars($arr['realm'],ENT_COMPAT,'UTF-8',false); - // You can have one and only one primary directory per realm. + // You can have one and only one primary directory per realm. // Downgrade any others claiming to be primary. As they have - // flubbed up this badly already, don't let them be directory servers at all. + // flubbed up this badly already, don't let them be directory servers at all. if(($site_directory === DIRECTORY_MODE_PRIMARY) && ($site_realm === get_directory_realm()) @@ -2586,7 +2551,6 @@ function import_site($arr,$pubkey) { $site_directory = DIRECTORY_MODE_NORMAL; } - if($exists) { if(($siterecord['site_flags'] != $site_directory) || ($siterecord['site_access'] != $access_policy) @@ -2644,11 +2608,9 @@ function import_site($arr,$pubkey) { } return $update; - } - /** * Send a zot packet to all hubs where this channel is duplicated, refreshing * such things as personal settings, channel permissions, address book updates, etc. @@ -2714,7 +2676,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { $info['config'] = $settings; } } - + if($channel) { $info['channel'] = array(); foreach($channel as $k => $v) { @@ -2775,23 +2737,20 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { if($interval) @time_sleep_until(microtime(true) + (float) $interval); } - - } function process_channel_sync_delivery($sender,$arr,$deliveries) { -// FIXME - this will sync red structures (channel, pconfig and abook). Eventually we need to make this application agnostic. - + /** @FIXME this will sync red structures (channel, pconfig and abook). Eventually we need to make this application agnostic. */ $result = array(); - - foreach($deliveries as $d) { + + foreach ($deliveries as $d) { $r = q("select * from channel where channel_hash = '%s' limit 1", dbesc($d['hash']) ); - if(! $r) { + if (! $r) { $result[] = array($d['hash'],'not found'); continue; } @@ -2801,7 +2760,6 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { $max_friends = service_class_fetch($channel['channel_id'],'total_channels'); $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']); $result[] = array($d['hash'],'channel mismatch',$channel['channel_name'],''); @@ -2832,8 +2790,6 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { } } - - if(array_key_exists('abook',$arr) && is_array($arr['abook']) && count($arr['abook'])) { $total_friends = 0; $total_feeds = 0; @@ -2922,7 +2878,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { } if($max_feeds !== false && ($clean['abook_flags'] & ABOOK_FLAG_FEED) && $total_feeds > $max_feeds) { logger('process_channel_sync_delivery: total_feeds service class limit exceeded'); - continue; + continue; } q("insert into abook ( abook_xchan, abook_channel ) values ('%s', %d ) ", dbesc($clean['abook_xchan']), @@ -2931,7 +2887,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { $total_friends ++; if($clean['abook_flags'] & ABOOK_FLAG_FEED) $total_feeds ++; - } + } if(count($clean)) { foreach($clean as $k => $v) { @@ -2975,7 +2931,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { if(intval($cl['deleted']) && (! intval($y['deleted']))) { q("delete from group_member where gid = %d", intval($y['id']) - ); + ); } } } @@ -3095,7 +3051,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { if(! $x) { q("insert into profile ( profile_guid, aid, uid ) values ('%s', %d, %d)", dbesc($profile['profile_guid']), - intval($channel['channel_account_id']), + intval($channel['channel_account_id']), intval($channel['channel_id']) ); $x = q("select * from profile where profile_guid = '%s' and uid = %d limit 1", @@ -3109,9 +3065,12 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { foreach($profile as $k => $v) { if(in_array($k,$disallowed)) continue; + $clean[$k] = $v; - // TODO - check if these are allowed, otherwise we'll error - // We also need to import local photos if a custom photo is selected + /** + * @TODO check if these are allowed, otherwise we'll error + * We also need to import local photos if a custom photo is selected + */ } if(count($clean)) { foreach($clean as $k => $v) { @@ -3121,49 +3080,58 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { } } } - - $result[] = array($d['hash'],'channel sync updated',$channel['channel_name'],''); - + $result[] = array($d['hash'],'channel sync updated',$channel['channel_name'],''); } + return $result; } // We probably should make rpost discoverable. - + function get_rpost_path($observer) { if(! $observer) return ''; + $parsed = parse_url($observer['xchan_url']); - return $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '') . '/rpost?f='; + return $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '') . '/rpost?f='; } + +/** + * @brief + * + * @param array $x + * @return boolean|string return false or a hash + */ function import_author_zot($x) { - $hash = make_xchan_hash($x['guid'],$x['guid_sig']); + $hash = make_xchan_hash($x['guid'], $x['guid_sig']); $r = q("select hubloc_url from hubloc where hubloc_guid = '%s' and hubloc_guid_sig = '%s' and (hubloc_flags & %d)>0 limit 1", dbesc($x['guid']), dbesc($x['guid_sig']), intval(HUBLOC_FLAGS_PRIMARY) ); - if($r) { + if ($r) { logger('import_author_zot: in cache', LOGGER_DEBUG); return $hash; } logger('import_author_zot: entry not in cache - probing: ' . print_r($x,true), LOGGER_DEBUG); - - $them = array('hubloc_url' => $x['url'],'xchan_guid' => $x['guid'], 'xchan_guid_sig' => $x['guid_sig']); - if(zot_refresh($them)) + + $them = array('hubloc_url' => $x['url'], 'xchan_guid' => $x['guid'], 'xchan_guid_sig' => $x['guid_sig']); + if (zot_refresh($them)) return $hash; + return false; } /** - * @function zot_process_message_request($data) - * If a site receives a comment to a post but finds they have no parent to attach it with, they + * @brief Process a message request. + * + * If a site receives a comment to a post but finds they have no parent to attach it with, they * may send a 'request' packet containing the message_id of the missing parent. This is the handler * for that packet. We will create a message_list array of the entire conversation starting with * the missing parent and invoke delivery to the sender of the packet. @@ -3173,20 +3141,21 @@ function import_author_zot($x) { * processed/delivered in order. * * Called from mod/post.php - */ - - + * + * @param array $data + * @return array + */ function zot_process_message_request($data) { $ret = array('success' => false); - if(! $data['message_id']) { + if (! $data['message_id']) { $ret['message'] = 'no message_id'; logger('no message_id'); return $ret; } $sender = $data['sender']; - $sender_hash = make_xchan_hash($sender['guid'],$sender['guid_sig']); + $sender_hash = make_xchan_hash($sender['guid'], $sender['guid_sig']); /* * Find the local channel in charge of this post (the first and only recipient of the request packet) @@ -3197,7 +3166,7 @@ function zot_process_message_request($data) { $c = q("select * from channel left join xchan on channel_hash = xchan_hash where channel_hash = '%s' limit 1", dbesc($recip_hash) ); - if(! $c) { + if (! $c) { logger('recipient channel not found.'); $ret['message'] .= 'recipient not found.' . EOL; return $ret; @@ -3209,7 +3178,7 @@ function zot_process_message_request($data) { $messages = zot_feed($c[0]['channel_id'],$sender_hash,array('message_id' => $data['message_id'])); - if($messages) { + if ($messages) { $env_recips = null; $r = q("select hubloc_guid, hubloc_url, hubloc_sitekey, hubloc_network, hubloc_flags, hubloc_callback, hubloc_host @@ -3219,20 +3188,18 @@ function zot_process_message_request($data) { intval(HUBLOC_FLAGS_DELETED), intval(HUBLOC_OFFLINE) ); - if(! $r) { + if (! $r) { logger('no hubs'); return $ret; } $hubs = $r; - $hublist = array(); - $keys = array(); - $private = ((array_key_exists('flags',$messages[0]) && in_array('private',$messages[0]['flags'])) ? true : false); + $private = ((array_key_exists('flags', $messages[0]) && in_array('private',$messages[0]['flags'])) ? true : false); if($private) - $env_recips = array('guid' => $sender['guid'],'guid_sig' => $sender['guid_sig'],'hash' => $sender_hash); + $env_recips = array('guid' => $sender['guid'], 'guid_sig' => $sender['guid_sig'], 'hash' => $sender_hash); $data_packet = json_encode(array('message_list' => $messages)); - + foreach($hubs as $hub) { $hash = random_string(); @@ -3260,10 +3227,10 @@ function zot_process_message_request($data) { * invoke delivery to send out the notify packet */ - proc_run('php','include/deliver.php',$hash); + proc_run('php', 'include/deliver.php', $hash); } - } $ret['success'] = true; + return $ret; } |