diff options
-rwxr-xr-x | include/items.php | 391 | ||||
-rw-r--r-- | include/zot.php | 548 |
2 files changed, 557 insertions, 382 deletions
diff --git a/include/items.php b/include/items.php index 1078103dc..e08aab85a 100755 --- a/include/items.php +++ b/include/items.php @@ -3,6 +3,9 @@ * @file include/items.php */ +/** @todo deprecated in newer SabreDAV releases Sabre\HTTP\URLUtil */ +use Sabre\DAV\URLUtil; + require_once('include/bbcode.php'); require_once('include/oembed.php'); require_once('include/crypto.php'); @@ -34,9 +37,9 @@ function collect_recipients($item, &$private_envelope) { $recipients = array_unique(array_merge($allow_people,$allow_groups)); - // if you specifically deny somebody but haven't allowed anybody, we'll allow everybody in your + // if you specifically deny somebody but haven't allowed anybody, we'll allow everybody in your // address book minus the denied connections. The post is still private and can't be seen publicly - // as that would allow the denied person to see the post by logging out. + // as that would allow the denied person to see the post by logging out. if((! $item['allow_cid']) && (! $item['allow_gid'])) { $r = q("select * from abook where abook_channel = %d and not (abook_flags & %d)>0 ", @@ -66,12 +69,12 @@ function collect_recipients($item, &$private_envelope) { } else { - // if the post is marked private but there are no recipients and public_policy/scope = self, + // if the post is marked private but there are no recipients and public_policy/scope = self, // only add the author and owner as recipients. The ACL for the post may live on the hub of // a different clone. We need to get the post to that hub. // The post may be private by virtue of not being visible to anybody on the internet, - // but there are no envelope recipients, so set this to false. Delivery is controlled + // but there are no envelope recipients, so set this to false. Delivery is controlled // by the directives in $item['public_policy']. $private_envelope = false; @@ -117,11 +120,11 @@ function collect_recipients($item, &$private_envelope) { $recipients = check_list_permissions($item['uid'],$recipients,'view_stream'); - // remove any upstream recipients from our list. + // remove any upstream recipients from our list. // If it is ourself we'll add it back in a second. - // This should prevent complex delivery chains from getting overly complex by not + // This should prevent complex delivery chains from getting overly complex by not // sending to anybody who is on our list of those who sent it to us. - + if($item['route']) { $route = explode(',',$item['route']); if(count($route)) { @@ -131,7 +134,7 @@ function collect_recipients($item, &$private_envelope) { } // add ourself just in case we have nomadic clones that need to get a copy. - + $recipients[] = $item['author_xchan']; if($item['owner_xchan'] != $item['author_xchan']) $recipients[] = $item['owner_xchan']; @@ -197,9 +200,9 @@ function comments_are_now_closed($item) { * sufficient privileges to comment. This will normally be called on a remote site where perm_is_allowed() * will not be suitable because the post owner does not have a local channel_id. * Generally we should look at the item - in particular the author['book_flags'] and see if ABOOK_FLAG_SELF is set. - * If it is, you should be able to use perm_is_allowed( ... 'post_comments'), and if it isn't you need to call + * 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. + * We also check the comments_closed date/time on the item if this is set. * * @param string $observer_xchan * @param array $item @@ -227,9 +230,9 @@ function can_comment_on_post($observer_xchan, $item) { return true; break; case 'public': - // We don't allow public comments yet, until a policy - // for dealing with anonymous comments is in place with - // a means to moderate comments. Until that time, return + // We don't allow public comments yet, until a policy + // for dealing with anonymous comments is in place with + // a means to moderate comments. Until that time, return // false. return false; break; @@ -256,9 +259,9 @@ function can_comment_on_post($observer_xchan, $item) { /** * @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, + * $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 + * loop detection and to avoid sending a particular item to any "upstream" sender (they * already have a copy because they sent it to us). * * Modifies item in the database pointed to by $iid. @@ -363,7 +366,7 @@ function red_zrlify_img_callback($matches) { * @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 + * Much more complex activities can be created. Permissions are checked. No filtering, tag expansion * or other processing is performed. * * @param array $arr @@ -441,7 +444,7 @@ function post_activity_item($arr) { $arr['deny_cid'] = ((x($arr,'deny_cid')) ? $arr['deny_cid'] : $channel['channel_deny_cid']); $arr['deny_gid'] = ((x($arr,'deny_gid')) ? $arr['deny_gid'] : $channel['channel_deny_gid']); - $arr['comment_policy'] = map_scope($channel['channel_w_comment']); + $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']; @@ -459,7 +462,7 @@ function post_activity_item($arr) { return $ret; } - $post = item_store($arr); + $post = item_store($arr); if($post['success']) $post_id = $post['item_id']; @@ -595,10 +598,17 @@ function get_feed_for($channel, $observer_hash, $params) { return $atom; } - +/** + * @brief + * + * @param array $item an associative array with + * * \b string \b verb + * @return string item's verb if set, default ACTIVITY_POST see boot.php + */ function construct_verb($item) { - if($item['verb']) + if ($item['verb']) return $item['verb']; + return ACTIVITY_POST; } @@ -632,7 +642,7 @@ function construct_activity_object($item) { } return ''; -} +} function construct_activity_target($item) { @@ -654,13 +664,15 @@ function construct_activity_target($item) { $r->link = str_replace('&','&', $r->link); $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"; } if($r->content) $o .= '<content type="html" >' . xmlify(bbcode($r->content)) . '</content>' . "\r\n"; + $o .= '</as:target>' . "\r\n"; + return $o; } @@ -674,7 +686,7 @@ function construct_activity_target($item) { * imported messages without including any embedded photos in the length. * * @param string $body - * @return string|unknown + * @return string */ function limit_body_size($body) { @@ -800,15 +812,15 @@ function get_item_elements($x) { if($arr['edited'] > datetime_convert()) $arr['edited'] = datetime_convert(); - $arr['expires'] = ((x($x,'expires') && $x['expires']) - ? datetime_convert('UTC','UTC',$x['expires']) + $arr['expires'] = ((x($x,'expires') && $x['expires']) + ? datetime_convert('UTC','UTC',$x['expires']) : NULL_DATE); - $arr['commented'] = ((x($x,'commented') && $x['commented']) - ? datetime_convert('UTC','UTC',$x['commented']) + $arr['commented'] = ((x($x,'commented') && $x['commented']) + ? datetime_convert('UTC','UTC',$x['commented']) : $arr['created']); - $arr['comments_closed'] = ((x($x,'comments_closed') && $x['comments_closed']) - ? datetime_convert('UTC','UTC',$x['comments_closed']) + $arr['comments_closed'] = ((x($x,'comments_closed') && $x['comments_closed']) + ? datetime_convert('UTC','UTC',$x['comments_closed']) : NULL_DATE); $arr['title'] = (($x['title']) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8',false) : ''); @@ -891,7 +903,7 @@ function get_item_elements($x) { // if it's a private post, encrypt it in the DB. // We have to do that here because we need to cleanse the input and prevent bad stuff from getting in, - // and we need plaintext to do that. + // and we need plaintext to do that. if(intval($arr['item_private'])) { @@ -918,7 +930,6 @@ function get_item_elements($x) { $arr['item_restrict'] = $x['item_restrict']; $arr['item_flags'] = $x['item_flags']; $arr['attach'] = $x['attach']; - } return $arr; @@ -949,10 +960,17 @@ function import_author_xchan($x) { return(($y) ? $y : false); } - +/** + * @brief Imports an author from Diaspora. + * + * @param array $x an associative array with + * * \e string \b address + * @return boolean|string false on error, otherwise xchan_hash of the new entry + */ function import_author_diaspora($x) { if(! $x['address']) return false; + if(discover_by_webbie($x['address'])) { $r = q("select xchan_hash from xchan where xchan_addr = '%s' limit 1", dbesc($x['address']) @@ -960,12 +978,20 @@ function import_author_diaspora($x) { if($r) return $r[0]['xchan_hash']; } + return false; } - +/** + * @brief Imports an author from a RSS feed. + * + * @param array $x an associative array with + * * \e string \b url + * * \e string \b name + * * \e string \b guid + * @return boolean|string + */ function import_author_rss($x) { - if(! $x['url']) return false; @@ -978,7 +1004,7 @@ function import_author_rss($x) { } $name = trim($x['name']); - $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_url, xchan_name, xchan_network ) + $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_url, xchan_name, xchan_network ) values ( '%s', '%s', '%s', '%s', '%s' )", dbesc($x['guid']), dbesc($x['guid']), @@ -986,13 +1012,15 @@ function import_author_rss($x) { dbesc(($name) ? $name : t('(Unknown)')), dbesc('rss') ); + if($r && $x['photo']) { $photos = import_profile_photo($x['photo']['src'],$x['url']); if($photos) { + /** @bug $arr is undefined in this SQL query */ $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_url = '%s' and xchan_network = 'rss'", - dbesc(datetime_convert('UTC','UTC',$arr['photo_updated'])), + dbesc(datetime_convert('UTC', 'UTC', $arr['photo_updated'])), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]), @@ -1022,7 +1050,7 @@ function import_author_unknown($x) { $name = trim($x['name']); - $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_url, xchan_name, xchan_network ) + $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_url, xchan_name, xchan_network ) values ( '%s', '%s', '%s', '%s', '%s' )", dbesc($x['url']), dbesc($x['url']), @@ -1035,6 +1063,7 @@ function import_author_unknown($x) { $photos = import_profile_photo($x['photo']['src'],$x['url']); if($photos) { + /** @bug $arr is undefined in this SQL query */ $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_url = '%s' and xchan_network = 'unknown'", dbesc(datetime_convert('UTC','UTC',$arr['photo_updated'])), dbesc($photos[0]), @@ -1082,7 +1111,7 @@ function encode_item($item,$mirror = false) { $item['body'] = crypto_unencapsulate(json_decode_plus($item['body']),$key); } - // If we're trying to backup an item so that it's recoverable or for export/imprt, + // If we're trying to backup an item so that it's recoverable or for export/imprt, // add all the attributes we need to recover it if($mirror) { @@ -1157,8 +1186,14 @@ function encode_item($item,$mirror = false) { return $x; } - -function map_scope($scope,$strip = false) { +/** + * @brief + * + * @param int $scope + * @param boolean $strip (optional) default false + * @return string + */ +function map_scope($scope, $strip = false) { switch($scope) { case 0: return 'self'; @@ -1180,6 +1215,12 @@ function map_scope($scope,$strip = false) { } } +/** + * @brief Returns a descriptive text for a given $scope. + * + * @param string $scope + * @return string translated string describing the scope + */ function translate_scope($scope) { if(! $scope || $scope === 'public') return t('Visible to anybody on the internet.'); @@ -1199,9 +1240,15 @@ function translate_scope($scope) { return t('Visible to specific connections.'); } +/** + * @brief + * + * @param array $xchan + * @return array an associative array + */ function encode_item_xchan($xchan) { - $ret = array(); + $ret['name'] = $xchan['xchan_name']; $ret['address'] = $xchan['xchan_addr']; $ret['url'] = (($xchan['hubloc_url']) ? $xchan['hubloc_url'] : $xchan['xchan_url']); @@ -1209,11 +1256,12 @@ function encode_item_xchan($xchan) { $ret['photo'] = array('mimetype' => $xchan['xchan_photo_mimetype'], 'src' => $xchan['xchan_photo_m']); $ret['guid'] = $xchan['xchan_guid']; $ret['guid_sig'] = $xchan['xchan_guid_sig']; + return $ret; } function encode_item_terms($terms) { - $ret = array(); + $ret = array(); $allowed_export_terms = array( TERM_UNKNOWN, TERM_HASHTAG, TERM_MENTION, TERM_CATEGORY, TERM_BOOKMARK ); @@ -1223,22 +1271,38 @@ function encode_item_terms($terms) { $ret[] = array('tag' => $term['term'], 'url' => $term['url'], 'type' => termtype($term['type'])); } } + return $ret; } +/** + * @brief + * + * @param int $t + * @return string + */ function termtype($t) { $types = array('unknown','hashtag','mention','category','private_category','file','search','thing','bookmark'); + return(($types[$t]) ? $types[$t] : 'unknown'); } +/** + * @brief + * + * @param array $t + * @return array|string empty string or array containing associative arrays with + * * \e string \b term + * * \e string \b url + * * \e int \b type + */ function decode_tags($t) { - if($t) { $ret = array(); foreach($t as $x) { $tag = array(); - $tag['term'] = htmlspecialchars($x['tag'], ENT_COMPAT,'UTF-8',false); - $tag['url'] = htmlspecialchars($x['url'], ENT_COMPAT,'UTF-8',false); + $tag['term'] = htmlspecialchars($x['tag'], ENT_COMPAT, 'UTF-8', false); + $tag['url'] = htmlspecialchars($x['url'], ENT_COMPAT, 'UTF-8', false); switch($x['type']) { case 'hashtag': $tag['type'] = TERM_HASHTAG; @@ -1271,6 +1335,7 @@ function decode_tags($t) { } $ret[] = $tag; } + return $ret; } @@ -1291,12 +1356,12 @@ function activity_sanitise($arr) { if(is_array($x)) $ret[$k] = activity_sanitise($x); else - $ret[$k] = htmlspecialchars($x, ENT_COMPAT,'UTF-8',false); + $ret[$k] = htmlspecialchars($x, ENT_COMPAT, 'UTF-8', false); } return $ret; } else { - return htmlspecialchars($arr, ENT_COMPAT,'UTF-8', false); + return htmlspecialchars($arr, ENT_COMPAT, 'UTF-8', false); } } @@ -1458,7 +1523,7 @@ function get_profile_elements($x) { $arr['postcode'] = (($x['postcode']) ? htmlspecialchars($x['postcode'], ENT_COMPAT,'UTF-8',false) : ''); $arr['country'] = (($x['country']) ? htmlspecialchars($x['country'], ENT_COMPAT,'UTF-8',false) : ''); - $arr['keywords'] = (($x['keywords'] && is_array($x['keywords'])) ? array_sanitise($x['keywords']) : array()); + $arr['keywords'] = (($x['keywords'] && is_array($x['keywords'])) ? array_sanitise($x['keywords']) : array()); return $arr; } @@ -1476,7 +1541,7 @@ function get_atom_elements($feed, $item, &$author) { $res = array(); $found_author = $item->get_author(); - if($found_author) { + if($found_author) { $author['author_name'] = unxmlify($found_author->get_name()); $author['author_link'] = unxmlify($found_author->get_link()); $author['author_is_feed'] = false; @@ -1604,7 +1669,7 @@ function get_atom_elements($feed, $item, &$author) { // make sure nobody is trying to sneak some html tags by us $res['body'] = notags(base64url_decode($res['body'])); - // We could probably turn these old Friendica bbcode bookmarks into bookmark tags but we'd have to + // We could probably turn these old Friendica bbcode bookmarks into bookmark tags but we'd have to // 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']); @@ -1612,14 +1677,14 @@ function get_atom_elements($feed, $item, &$author) { $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 - // the content type. Our own network only emits text normally, though it might have been converted to + // It isn't certain at this point whether our content is plaintext or html and we'd be foolish to trust + // the content type. Our own network only emits text normally, though it might have been converted to // html if we used a pubsubhubbub transport. But if we see even one html tag in our text, we will // have to assume it is all html and needs to be purified. - // It doesn't matter all that much security wise - because before this content is used anywhere, we are - // going to escape any tags we find regardless, but this lets us import a limited subset of html from - // the wild, by sanitising it and converting supported tags to bbcode before we rip out any remaining + // It doesn't matter all that much security wise - because before this content is used anywhere, we are + // going to escape any tags we find regardless, but this lets us import a limited subset of html from + // the wild, by sanitising it and converting supported tags to bbcode before we rip out any remaining // html. if((strpos($res['body'],'<') !== false) && (strpos($res['body'],'>') !== false)) { @@ -1682,7 +1747,7 @@ function get_atom_elements($feed, $item, &$author) { $res['edited'] = unxmlify($rawedited[0]['data']); if((x($res,'edited')) && (! (x($res,'created')))) - $res['created'] = $res['edited']; + $res['created'] = $res['edited']; if(! $res['created']) $res['created'] = $item->get_date('c'); @@ -1783,7 +1848,6 @@ function get_atom_elements($feed, $item, &$author) { $attach = $item->get_enclosures(); if($attach) { $res['attach'] = array(); - $att_arr = array(); foreach($attach as $att) { $len = intval($att->get_length()); $link = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_link())))); @@ -1812,7 +1876,7 @@ function get_atom_elements($feed, $item, &$author) { if($child[NAMESPACE_ACTIVITY]['obj_type'][0]['data']) { $res['obj_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']) @@ -1906,14 +1970,22 @@ function encode_rel_links($links) { return xmlify($o); } -function item_store($arr,$allow_exec = false) { +/** + * @brief + * + * @param array $arr + * @param boolean $allow_exec (optional) default false + * @return array + * * \e boolean \b success + * * \e int \b item_id + */ +function item_store($arr, $allow_exec = false) { $d = array('item' => $arr, 'allow_exec' => $allow_exec); call_hooks('item_store', $d ); $arr = $d['item']; $allow_exec = $d['allow_exec']; - $ret = array('success' => false, 'item_id' => 0); if(! $arr['uid']) { @@ -1924,7 +1996,7 @@ function item_store($arr,$allow_exec = false) { //$uplinked_comment = false; - // If a page layout is provided, ensure it exists and belongs to us. + // If a page layout is provided, ensure it exists and belongs to us. if(array_key_exists('layout_mid',$arr) && $arr['layout_mid']) { $l = q("select item_restrict from item where mid = '%s' and uid = %d limit 1", @@ -1980,7 +2052,7 @@ function item_store($arr,$allow_exec = false) { } $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); - + if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) { $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false); call_hooks('item_translate', $translate); @@ -2075,7 +2147,7 @@ function item_store($arr,$allow_exec = false) { $comments_closed = $arr['comments_closed']; $arr['item_flags'] = $arr['item_flags'] | ITEM_THREAD_TOP; } - else { + else { // find the parent and snarf the item id and ACL's // and anything else we need to inherit @@ -2112,7 +2184,7 @@ function item_store($arr,$allow_exec = false) { if($r[0]['mid'] != $r[0]['parent_mid']) { $arr['parent_mid'] = $r[0]['parent_mid']; - $z = q("SELECT * FROM `item` WHERE `mid` = '%s' AND `parent_mid` = '%s' AND `uid` = %d + $z = q("SELECT * FROM `item` WHERE `mid` = '%s' AND `parent_mid` = '%s' AND `uid` = %d ORDER BY `id` ASC LIMIT 1", dbesc($r[0]['parent_mid']), dbesc($r[0]['parent_mid']), @@ -2132,7 +2204,7 @@ function item_store($arr,$allow_exec = false) { $comments_closed = $r[0]['comments_closed']; if($r[0]['item_flags'] & ITEM_WALL) - $arr['item_flags'] = $arr['item_flags'] | ITEM_WALL; + $arr['item_flags'] = $arr['item_flags'] | ITEM_WALL; // An uplinked comment might arrive with a downstream owner. // Fix it. @@ -2149,7 +2221,7 @@ function item_store($arr,$allow_exec = false) { // Edge case. We host a public forum that was originally posted to privately. // The original author commented, but as this is a comment, the permissions - // weren't fixed up so it will still show the comment as private unless we fix it here. + // weren't fixed up so it will still show the comment as private unless we fix it here. if((intval($r[0]['item_flags']) & ITEM_UPLINK) && (! $r[0]['item_private'])) $arr['item_private'] = 0; @@ -2196,7 +2268,7 @@ function item_store($arr,$allow_exec = false) { if(strlen($allow_cid) || strlen($allow_gid) || strlen($deny_cid) || strlen($deny_gid) || strlen($public_policy)) $private = 1; else - $private = $arr['item_private']; + $private = $arr['item_private']; $arr['parent'] = $parent_id; $arr['allow_cid'] = $allow_cid; @@ -2211,10 +2283,10 @@ function item_store($arr,$allow_exec = false) { dbesc_array($arr); - $r = dbq("INSERT INTO `item` (`" - . implode("`, `", array_keys($arr)) - . "`) VALUES ('" - . implode("', '", array_values($arr)) + $r = dbq("INSERT INTO `item` (`" + . implode("`, `", array_keys($arr)) + . "`) VALUES ('" + . implode("', '", array_values($arr)) . "')" ); // find the item we just created @@ -2289,7 +2361,7 @@ function item_store($arr,$allow_exec = false) { // If _creating_ a deleted item, don't propagate it further or send out notifications. // We need to store the item details just in case the delete came in before the original post, - // so that we have an item in the DB that's marked deleted and won't store a fresh post + // so that we have an item in the DB that's marked deleted and won't store a fresh post // that isn't aware that we were already told to delete it. if(! ($arr['item_restrict'] & ITEM_DELETED)) { @@ -2377,7 +2449,7 @@ function item_store_update($arr,$allow_exec = false) { } $allowed_languages = get_pconfig($arr['uid'],'system','allowed_languages'); - + if((is_array($allowed_languages)) && ($arr['lang']) && (! array_key_exists($arr['lang'],$allowed_languages))) { $translate = array('item' => $arr, 'from' => $arr['lang'], 'to' => $allowed_languages, 'translated' => false); call_hooks('item_translate', $translate); @@ -2491,7 +2563,7 @@ function item_store_update($arr,$allow_exec = false) { if($str) $str .= ","; $str .= " `" . $k . "` = '" . $v . "' "; - } + } $r = dbq("update `item` set " . $str . " where id = " . $orig_post_id ); @@ -2537,7 +2609,7 @@ function item_store_update($arr,$allow_exec = false) { function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, $walltowall = false) { - // We won't be able to sign Diaspora comments for authenticated visitors + // We won't be able to sign Diaspora comments for authenticated visitors // - we don't have their private key // since Diaspora doesn't handle edits we can only do this for the original text and not update it. @@ -2548,9 +2620,9 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, if($walltowall) { logger('wall to wall comment',LOGGER_DEBUG); // post will come across with the owner's identity. Throw a preamble onto the post to indicate the true author. - $signed_body = "\n\n" + $signed_body = "\n\n" . '![' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_photo_m'] . ')' - . '[' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_url'] . ')' . "\n\n" + . '[' . $datarray['author']['xchan_name'] . '](' . $datarray['author']['xchan_url'] . ')' . "\n\n" . $signed_body; } @@ -2573,7 +2645,7 @@ function store_diaspora_comment_sig($datarray, $channel, $parent_item, $post_id, $r = q("update item set diaspora_meta = '%s' where id = %d", dbesc(json_encode($y)), - intval($post_id) + intval($post_id) ); if(! $r) @@ -2697,7 +2769,7 @@ function tag_deliver($uid, $item_id) { $item = $i[0]; - if(($item['source_xchan']) && ($item['item_flags'] & ITEM_UPLINK) + if(($item['source_xchan']) && ($item['item_flags'] & ITEM_UPLINK) && ($item['item_flags'] & ITEM_THREAD_TOP) && ($item['edited'] != $item['created'])) { // this is an update (edit) to a post which was already processed by us and has a second delivery chain // Just start the second delivery chain to deliver the updated post @@ -2712,7 +2784,7 @@ function tag_deliver($uid, $item_id) { if (stristr($item['verb'],ACTIVITY_POKE)) { $poke_notify = true; - if(($item['obj_type'] == "") || ($item['obj_type'] !== ACTIVITY_OBJ_PERSON) || (! $item['object'])) + if(($item['obj_type'] == "") || ($item['obj_type'] !== ACTIVITY_OBJ_PERSON) || (! $item['object'])) $poke_notify = false; $obj = json_decode_plus($item['object']); @@ -2748,7 +2820,7 @@ function tag_deliver($uid, $item_id) { // We received a community tag activity for a post. // See if we are the owner of the parent item and have given permission to tag our posts. // If so tag the parent post. - + logger('tag_deliver: community tag activity received'); if(($item['owner_xchan'] === $u[0]['channel_hash']) && (! get_pconfig($u[0]['channel_id'],'system','blocktags'))) { @@ -2839,7 +2911,7 @@ function tag_deliver($uid, $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 - // If it's private we may have to unobscure it momentarily so that we can parse it. + // If it's private we may have to unobscure it momentarily so that we can parse it. $body = ''; @@ -2849,7 +2921,7 @@ function tag_deliver($uid, $item_id) { $body = crypto_unencapsulate(json_decode_plus($item['body']),$key); } else - $body = $item['body']; + $body = $item['body']; $body = preg_replace('/\[share(.*?)\[\/share\]/','',$body); @@ -2858,7 +2930,7 @@ function tag_deliver($uid, $item_id) { $matches = array(); $pattern = '/@\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/'; - if(preg_match($pattern,$body,$matches)) + if(preg_match($pattern,$body,$matches)) $tagged = true; $pattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/'; @@ -2927,9 +2999,9 @@ function tag_deliver($uid, $item_id) { // prevent delivery looping - only proceed // if the message originated elsewhere and is a top-level post - if(($item['item_flags'] & ITEM_WALL) - || ($item['item_flags'] & ITEM_ORIGIN) - || (!($item['item_flags'] & ITEM_THREAD_TOP)) + if(($item['item_flags'] & ITEM_WALL) + || ($item['item_flags'] & ITEM_ORIGIN) + || (!($item['item_flags'] & ITEM_THREAD_TOP)) || ($item['id'] != $item['parent'])) { logger('tag_deliver: item was local or a comment. rejected.'); return; @@ -2945,7 +3017,7 @@ function tag_deliver($uid, $item_id) { * 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. + * By then it would be too late to reject it. */ function tgroup_check($uid,$item) { @@ -3045,8 +3117,8 @@ function tgroup_check($uid,$item) { /** * Sourced and tag-delivered posts are re-targetted for delivery to the connections of the channel - * 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. + * 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 @@ -3059,7 +3131,7 @@ 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 - $private = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] + $private = (($channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 1 : 0); $new_public_policy = map_scope($channel['channel_r_stream'],true); @@ -3070,14 +3142,14 @@ function start_delivery_chain($channel, $item, $item_id, $parent) { $flag_bits = $item['item_flags'] | ITEM_WALL; // The message didn't necessarily originate on this site, (we'll honour it if it did), - // but the parent post of this thread will be reset as a local post, as it is the top of + // but the parent post of this thread will be reset as a local post, as it is the top of // this delivery chain and is coming from this site, regardless of where the original // originated. if(! $parent) $flag_bits = $flag_bits | ITEM_ORIGIN; - // unset the nocomment bit if it's there. + // unset the nocomment bit if it's there. if($flag_bits & ITEM_NOCOMMENT) $flag_bits = $flag_bits ^ ITEM_NOCOMMENT; @@ -3122,7 +3194,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent) { } } - $r = q("update item set item_flags = %d, owner_xchan = '%s', allow_cid = '%s', allow_gid = '%s', + $r = q("update item set item_flags = %d, owner_xchan = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', item_private = %d, public_policy = '%s', comment_policy = '%s', title = '%s', body = '%s' where id = %d", intval($flag_bits), dbesc($channel['channel_hash']), @@ -3147,7 +3219,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent) { /** * @brief * - * Checks to see if this item owner is referenced as a source for this channel and if the post + * 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. * @@ -3214,7 +3286,7 @@ function mail_store($arr) { return 0; } - if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false)) + if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false)) $arr['body'] = escape_tags($arr['body']); if(array_key_exists('attach',$arr) && is_array($arr['attach'])) @@ -3257,10 +3329,10 @@ function mail_store($arr) { logger('mail_store: ' . print_r($arr,true), LOGGER_DATA); - $r = dbq("INSERT INTO mail (`" - . implode("`, `", array_keys($arr)) - . "`) VALUES ('" - . implode("', '", array_values($arr)) + $r = dbq("INSERT INTO mail (`" + . implode("`, `", array_keys($arr)) + . "`) VALUES ('" + . implode("', '", array_values($arr)) . "')" ); // find the item we just created @@ -3309,7 +3381,7 @@ function mail_store($arr) { /** * @brief Process atom feed and update anything/everything we might need to update. * - * $hub = should we find a hub declation in the feed, pass it back to our calling process, who might (or + * $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 * @@ -3320,9 +3392,9 @@ function mail_store($arr) { * 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 + * 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 + * @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. @@ -3426,14 +3498,14 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $author['author_name'] = $contact['xchan_name']; if((! x($author,'author_link')) || ($author['author_is_feed'])) $author['author_link'] = $contact['xchan_url']; - if((! x($author,'author_photo'))|| ($author['author_is_feed'])) + if((! x($author,'author_photo'))|| ($author['author_is_feed'])) $author['author_photo'] = $contact['xchan_photo_m']; $datarray['author_xchan'] = ''; if($author['author_link'] != $contact['xchan_url']) { $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo']))); - if($x) + if($x) $datarray['author_xchan'] = $x; } if(! $datarray['author_xchan']) @@ -3449,8 +3521,8 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { // Update content if 'updated' changes if($r) { - if((x($datarray,'edited') !== false) - && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { + if((x($datarray,'edited') !== false) + && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { // do not accept (ignore) an earlier edit than one we currently have. if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited']) @@ -3483,7 +3555,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $author['author_name'] = $contact['xchan_name']; if((! x($author,'author_link')) || ($author['author_is_feed'])) $author['author_link'] = $contact['xchan_url']; - if((! x($author,'author_photo'))|| ($author['author_is_feed'])) + if((! x($author,'author_photo'))|| ($author['author_is_feed'])) $author['author_photo'] = $contact['xchan_photo_m']; } @@ -3496,7 +3568,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { if($author['author_link'] != $contact['xchan_url']) { $x = import_author_unknown(array('name' => $author['author_name'],'url' => $author['author_link'],'photo' => array('src' => $author['author_photo']))); - if($x) + if($x) $datarray['author_xchan'] = $x; } if(! $datarray['author_xchan']) @@ -3512,8 +3584,8 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { // Update content if 'updated' changes if($r) { - if((x($datarray,'edited') !== false) - && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { + if((x($datarray,'edited') !== false) + && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { // do not accept (ignore) an earlier edit than one we currently have. if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited']) @@ -3535,7 +3607,7 @@ function consume_feed($xml, $importer, &$contact, $pass = 0) { $author['owner_avatar'] = $contact['thumb']; } - logger('consume_feed: author ' . print_r($author,true),LOGGER_DEBUG); + logger('consume_feed: author ' . print_r($author,true),LOGGER_DEBUG); logger('consume_feed: ' . print_r($datarray,true),LOGGER_DATA); @@ -3673,7 +3745,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { // $mentioned = get_mentions($item,$tags); // if($mentioned) // $o .= $mentioned; - + call_hooks('atom_entry', $o); $o .= '</entry>' . "\r\n"; @@ -3719,7 +3791,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { // Check to see if we should replace this photo link with an embedded image // 1. No need to do so if the photo is public // 2. If there's a contact-id provided, see if they're in the access list - // for the photo. If so, embed it. + // for the photo. If so, embed it. // 3. Otherwise, if we have an item, see if the item permissions match the photo // permissions, regardless of order but first check to see if they're an exact // match to save some processing overhead. @@ -3728,7 +3800,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { if($cid) { $recips = enumerate_permissions($r[0]); if(in_array($cid, $recips)) { - $replace = true; + $replace = true; } } elseif($item) { @@ -3787,7 +3859,7 @@ function has_permissions($obj) { } function compare_permissions($obj1,$obj2) { - // first part is easy. Check that these are exactly the same. + // first part is easy. Check that these are exactly the same. if(($obj1['allow_cid'] == $obj2['allow_cid']) && ($obj1['allow_gid'] == $obj2['allow_gid']) && ($obj1['deny_cid'] == $obj2['deny_cid']) @@ -3882,10 +3954,10 @@ function item_expire($uid,$days) { $sql_extra = ((intval($expire_network_only)) ? " AND (item_flags & " . intval(ITEM_WALL) . ") = 0 " : ""); - $r = q("SELECT * FROM `item` - WHERE `uid` = %d - AND `created` < %s - INTERVAL %s - AND `id` = `parent` + $r = q("SELECT * FROM `item` + WHERE `uid` = %d + AND `created` < %s - INTERVAL %s + AND `id` = `parent` $sql_extra AND ( item_flags & %d ) = 0 AND ( item_restrict = 0 ) LIMIT $expire_limit ", @@ -3956,7 +4028,7 @@ function drop_items($items) { // Delete item with given item $id. $interactive means we're running interactively, and must check // permissions to carry out this act. If it is non-interactive, we are deleting something at the -// system's request and do not check permission. This is very important to know. +// system's request and do not check permission. This is very important to know. // Some deletion requests (those coming from remote sites) must be staged. // $stage = 0 => unstaged @@ -4006,7 +4078,7 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal if($ok_to_delete) { - // set the deleted flag immediately on this item just in case the + // set the deleted flag immediately on this item just in case the // hook calls a remote process which loops. We'll delete it properly in a second. $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ) WHERE id = %d", @@ -4034,12 +4106,12 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal return 1; // send the notification upstream/downstream as the case may be - // only send notifications to others if this is the owner's wall item. + // only send notifications to others if this is the owner's wall item. - // This isn't optimal. We somehow need to pass to this function whether or not - // to call the notifier, or we need to call the notifier from the calling function. + // This isn't optimal. We somehow need to pass to this function whether or not + // to call the notifier, or we need to call the notifier from the calling function. // We'll rely on the undocumented behaviour that DROPITEM_PHASE1 is (hopefully) only - // set if we know we're going to send delete notifications out to others. + // set if we know we're going to send delete notifications out to others. if((($item['item_flags'] & ITEM_WALL) && ($stage != DROPITEM_PHASE2)) || ($stage == DROPITEM_PHASE1)) proc_run('php','include/notifier.php','drop',$notify_id); @@ -4093,7 +4165,7 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) { case DROPITEM_NORMAL: default: if($linked_item && ! $force) { - $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), + $r = q("UPDATE item SET item_restrict = ( item_restrict | %d ), changed = '%s', edited = '%s' WHERE id = %d", intval(ITEM_HIDDEN), dbesc(datetime_convert()), @@ -4113,7 +4185,7 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) { break; } - // immediately remove any undesired profile likes. + // immediately remove any undesired profile likes. q("delete from likes where iid = %d and channel_id = %d", intval($item['id']), @@ -4167,8 +4239,8 @@ 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 + * 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 @@ -4186,7 +4258,7 @@ function list_post_dates($uid, $wall, $mindate) { if(! $dthen) return array(); - // If it's near the end of a long month, backup to the 28th so that in + // If it's near the end of a long month, backup to the 28th so that in // consecutive loops we'll always get a whole month difference. if(intval(substr($dnow,8)) > 28) @@ -4221,7 +4293,7 @@ function posted_dates($uid,$wall) { if(! $dthen) return array(); - // If it's near the end of a long month, backup to the 28th so that in + // If it's near the end of a long month, backup to the 28th so that in // consecutive loops we'll always get a whole month difference. if(intval(substr($dnow,8)) > 28) @@ -4248,7 +4320,7 @@ function posted_dates($uid,$wall) { function fetch_post_tags($items,$link = false) { $tag_finder = array(); - if($items) { + if($items) { foreach($items as $item) { if(is_array($item)) { if(array_key_exists('item_id',$item)) { @@ -4348,7 +4420,7 @@ function zot_feed($uid,$observer_xchan,$arr) { /** @FIXME fix this part for PostgreSQL */ - if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { + if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { return array(); } @@ -4356,8 +4428,8 @@ function zot_feed($uid,$observer_xchan,$arr) { require_once('include/security.php'); $r = q("SELECT parent, created from item WHERE uid != %d - AND item_private = 0 AND item_restrict = 0 AND uid in (" . stream_perms_api_uids(PERMS_PUBLIC,10,1) . ") - AND (item_flags & %d) > 0 + AND item_private = 0 AND item_restrict = 0 AND uid in (" . stream_perms_api_uids(PERMS_PUBLIC,10,1) . ") + AND (item_flags & %d) > 0 $sql_extra GROUP BY parent ORDER BY created ASC $limit", intval($uid), intval(ITEM_WALL) @@ -4366,7 +4438,7 @@ function zot_feed($uid,$observer_xchan,$arr) { else { $r = q("SELECT parent, created from item WHERE uid = %d AND item_restrict = 0 - AND (item_flags & %d) > 0 + AND (item_flags & %d) > 0 $sql_extra GROUP BY parent ORDER BY created ASC $limit", intval($uid), intval(ITEM_WALL) @@ -4376,8 +4448,8 @@ function zot_feed($uid,$observer_xchan,$arr) { if($r) { $parents_str = ids_to_querystr($r,'parent'); $sys_query = ((is_sys_channel($uid)) ? $sql_extra : ''); - - $items = q("SELECT `item`.*, `item`.`id` AS `item_id` FROM `item` + + $items = q("SELECT `item`.*, `item`.`id` AS `item_id` FROM `item` WHERE `item`.`item_restrict` = 0 AND `item`.`parent` IN ( %s ) $sys_query ", dbesc($parents_str) @@ -4458,7 +4530,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $contact_str .= "'" . $c['xchan'] . "'"; } } else { - $contact_str = ' 0 '; + $contact_str = ' 0 '; $result['message'] = t('Collection is empty.'); return $result; } @@ -4496,12 +4568,12 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C } if($arr['search']) { - if(strpos($arr['search'],'#') === 0) - $sql_extra .= term_query('item',substr($arr['search'],1),TERM_HASHTAG); - else - $sql_extra .= sprintf(" AND item.body like '%s' ", - dbesc(protect_sprintf('%' . $arr['search'] . '%')) - ); + if(strpos($arr['search'],'#') === 0) + $sql_extra .= term_query('item',substr($arr['search'],1),TERM_HASHTAG); + else + $sql_extra .= sprintf(" AND item.body like '%s' ", + dbesc(protect_sprintf('%' . $arr['search'] . '%')) + ); } if (strlen($arr['file'])) { @@ -4542,6 +4614,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $sql_nets .= "( abook.abook_closeness >= " . intval($arr['cmin']) . " "; $sql_nets .= " AND abook.abook_closeness <= " . intval($arr['cmax']) . " ) "; + /** @fixme dead code, $cmax is undefined */ if ($cmax == 99) $sql_nets .= " OR abook.abook_closeness IS NULL ) "; } @@ -4564,12 +4637,12 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C 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 - $simple_update - $sql_extra $sql_nets - ORDER BY item.received DESC $pager_sql " - ); + $items = q("SELECT item.*, item.id AS item_id FROM item + WHERE $item_uids $item_restrict + $simple_update + $sql_extra $sql_nets + ORDER BY item.received DESC $pager_sql" + ); require_once('include/items.php'); @@ -4598,7 +4671,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C ORDER BY item.$ordering DESC $pager_sql ", intval(ABOOK_FLAG_BLOCKED) ); - + } else { // update @@ -4629,7 +4702,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C dbesc($parents_str) ); - $second = dba_timer(); + //$second = dba_timer(); xchan_query($items); @@ -4673,9 +4746,9 @@ function update_remote_id($channel,$post_id,$webpage,$pagetitle,$namespace,$remo if($page_type) { - // store page info as an alternate message_id so we can access it via + // store page info as an alternate message_id so we can access it via // https://sitename/page/$channelname/$pagetitle - // if no pagetitle was given or it couldn't be transliterated into a url, use the first + // if no pagetitle was given or it couldn't be transliterated into a url, use the first // sixteen bytes of the mid - which makes the link portable and not quite as daunting // as the entire mid. If it were the post_id the link would be less portable. @@ -4750,9 +4823,9 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, if ($first_access_tag && (! get_pconfig($profile_uid,'system','no_private_mention_acl_override'))) { // This is a tough call, hence configurable. The issue is that one can type in a @!privacy mention - // and also have a default ACL (perhaps from viewing a collection) and could be suprised that the + // and also have a default ACL (perhaps from viewing a collection) and could be suprised that the // privacy mention wasn't the only recipient. So the default is to wipe out the existing ACL if a - // private mention is found. This can be over-ridden if you wish private mentions to be in + // private mention is found. This can be over-ridden if you wish private mentions to be in // addition to the current ACL settings. $str_contact_allow = ''; @@ -4775,7 +4848,7 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, * 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. + * cause looping, so use this hackish but accurate method. * * @param array $item * @return boolean diff --git a/include/zot.php b/include/zot.php index 28a2e8957..3c7413b5c 100644 --- a/include/zot.php +++ b/include/zot.php @@ -32,6 +32,7 @@ require_once('include/hubloc.php'); */ function zot_new_uid($channel_nick) { $rawstr = z_root() . '/' . $channel_nick . '.' . mt_rand(); + return(base64url_encode(hash('whirlpool', $rawstr, true), true)); } @@ -40,8 +41,9 @@ function zot_new_uid($channel_nick) { * * 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. + * + * @note 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 @@ -116,7 +118,7 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot 'guid_sig' => base64url_encode(rsa_sign($channel['channel_guid'],$channel['channel_prvkey'])), 'url' => z_root(), 'url_sig' => base64url_encode(rsa_sign(z_root(),$channel['channel_prvkey'])) - ), + ), 'callback' => '/post', 'version' => ZOT_REVISION ); @@ -124,11 +126,12 @@ function zot_build_packet($channel, $type = 'notify', $recipients = null, $remot if ($recipients) { for ($x = 0; $x < count($recipients); $x ++) unset($recipients[$x]['hash']); + $data['recipients'] = $recipients; } if ($secret) { - $data['secret'] = $secret; + $data['secret'] = $secret; $data['secret_sig'] = base64url_encode(rsa_sign($secret,$channel['channel_prvkey'])); } @@ -195,7 +198,7 @@ function zot_finger($webbie, $channel = null, $autofallback = true) { // The webbie we were called with may not, so it might not be found // unless we query for hubloc_addr instead of xchan_addr - $r = q("select xchan.*, hubloc.* from xchan + $r = q("select xchan.*, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash where xchan_addr = '%s' and (hubloc_flags & %d) > 0 limit 1", dbesc($xchan_addr), @@ -257,19 +260,19 @@ function zot_finger($webbie, $channel = null, $autofallback = true) { * @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. + * 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. + * 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 + * 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. + * 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 @@ -376,7 +379,7 @@ function zot_refresh($them, $channel = null, $force = false) { if($k === 'connected') { $connected_set = intval($v); continue; - } + } if(($v) && (array_key_exists($k,$global_perms))) { $their_perms = $their_perms | intval($global_perms[$k][1]); } @@ -389,7 +392,7 @@ function zot_refresh($them, $channel = null, $force = false) { intval(ABOOK_FLAG_SELF) ); - if(array_key_exists('profile',$j) && array_key_exists('next_birthday',$j['profile'])) { + if(array_key_exists('profile',$j) && array_key_exists('next_birthday',$j['profile'])) { $next_birthday = datetime_convert('UTC','UTC',$j['profile']['next_birthday']); } else { @@ -398,9 +401,9 @@ function zot_refresh($them, $channel = null, $force = false) { if($r) { - // if the dob is the same as what we have stored (disregarding the year), keep the one + // if the dob is the same as what we have stored (disregarding the year), keep the one // we have as we may have updated the year after sending a notification; and resetting - // to the one we just received would cause us to create duplicated events. + // to the one we just received would cause us to create duplicated events. if(substr($r[0]['abook_dob'],5) == substr($next_birthday,5)) $next_birthday = $r[0]['abook_dob']; @@ -408,7 +411,7 @@ function zot_refresh($them, $channel = null, $force = false) { $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 + where abook_xchan = '%s' and abook_channel = %d and not (abook_flags & %d) > 0 ", intval($their_perms), dbescdate($next_birthday), @@ -420,11 +423,11 @@ function zot_refresh($them, $channel = null, $force = false) { // if(($connected_set === 0 || $connected_set === 1) && ($connected_set !== $current_abook_unconnected)) { // 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. + // match your current connected state setting, toggle it. /** @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 +// where abook_xchan = '%s' and abook_channel = %d // and not (abook_flags & %d) limit 1", // intval(ABOOK_FLAG_UNCONNECTED), // dbesc($x['hash']), @@ -438,7 +441,7 @@ function zot_refresh($them, $channel = null, $force = false) { else { // if we were just granted read stream permission and didn't have it before, try to pull in some posts if((! ($r[0]['abook_their_perms'] & PERMS_R_STREAM)) && ($their_perms & PERMS_R_STREAM)) - proc_run('php','include/onepoll.php',$r[0]['abook_id']); + proc_run('php','include/onepoll.php',$r[0]['abook_id']); } } else { @@ -450,7 +453,7 @@ function zot_refresh($them, $channel = null, $force = false) { } if(! $default_perms) $default_perms = intval(get_pconfig($channel['channel_id'],'system','autoperms')); - + // Keep original perms to check if we need to notify them $previous_perms = get_all_perms($channel['channel_id'],$x['hash']); @@ -493,23 +496,24 @@ function zot_refresh($them, $channel = null, $force = false) { if($new_connection) { require_once('include/enotify.php'); notification(array( - 'type' => NOTIFY_INTRO, - 'from_xchan' => $x['hash'], - 'to_xchan' => $channel['channel_hash'], - 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'], + 'type' => NOTIFY_INTRO, + 'from_xchan' => $x['hash'], + 'to_xchan' => $channel['channel_hash'], + 'link' => z_root() . '/connedit/' . $new_connection[0]['abook_id'], )); } if($new_connection && ($their_perms & PERMS_R_STREAM)) { if(($channel['channel_w_stream'] & PERMS_PENDING) || (! ($new_connection[0]['abook_flags'] & ABOOK_FLAG_PENDING)) ) - proc_run('php','include/onepoll.php',$new_connection[0]['abook_id']); + proc_run('php','include/onepoll.php',$new_connection[0]['abook_id']); } } } } return true; } + return false; } @@ -521,7 +525,7 @@ function zot_refresh($them, $channel = null, $force = false) { * 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 an assoziative array which must contain: + * @param array $arr an associative 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 @@ -549,8 +553,8 @@ function zot_gethub($arr) { return null; } - $r = q("select * from hubloc - where hubloc_guid = '%s' and hubloc_guid_sig = '%s' + $r = q("select * from hubloc + where hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' limit 1", dbesc($arr['guid']), @@ -564,24 +568,25 @@ function zot_gethub($arr) { } } logger('zot_gethub: not found: ' . print_r($arr,true), LOGGER_DEBUG); + return null; } /** * @brief Registers an unknown hup. * - * A communication has been received which has an unknown (to us) sender. + * 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 an assoziative array which must contain: + * @param array $arr an associative 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 an assoziative array with: + * @returns array an associative array with * * \b success boolean true or false * * \b message (optional) error string only if success is false */ @@ -604,8 +609,8 @@ function zot_register_hub($arr) { if($x['success']) { $record = json_decode($x['body'],true); - /* - * We now have a key - only continue registration if our signatures are valid + /* + * We now have a key - only continue registration if our signatures are valid * AND the guid and guid sig in the returned packet match those provided in * our current communication. */ @@ -621,7 +626,7 @@ function zot_register_hub($arr) { } else { logger('zot_register_hub: failure to verify returned packet.'); - } + } } } @@ -639,7 +644,7 @@ function zot_register_hub($arr) { * this typically occurs once a month for each channel as part of a scheduled ping to notify the directory * that the channel still exists * @param array $ud_arr - * If set [typically by update_directory_entry()] indicates a specific update table row and more particularly + * If set [typically by update_directory_entry()] indicates a specific update table row and more particularly * contains a particular address (ud_addr) which needs to be updated in that table. * * @return associative array @@ -651,7 +656,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { call_hooks('import_xchan', $arr); $ret = array('success' => false); - $dirmode = intval(get_config('system','directory_mode')); + $dirmode = intval(get_config('system','directory_mode')); $changed = false; $what = ''; @@ -697,7 +702,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { // 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 */ - $dirmode = get_config('system','directory_mode'); + $dirmode = get_config('system','directory_mode'); if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) && ($arr['site']['url'] != z_root())) $arr['searchable'] = false; @@ -725,14 +730,14 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { if($pubforum_changed) $new_flags = $r[0]['xchan_flags'] ^ XCHAN_FLAGS_PUBFORUM; - if(($r[0]['xchan_name_date'] != $arr['name_updated']) - || ($r[0]['xchan_connurl'] != $arr['connections_url']) + if(($r[0]['xchan_name_date'] != $arr['name_updated']) + || ($r[0]['xchan_connurl'] != $arr['connections_url']) || ($r[0]['xchan_flags'] != $new_flags) || ($r[0]['xchan_addr'] != $arr['address']) || ($r[0]['xchan_follow'] != $arr['follow_url']) - || ($r[0]['xchan_connpage'] != $arr['connect_url']) + || ($r[0]['xchan_connpage'] != $arr['connect_url']) || ($r[0]['xchan_url'] != $arr['url'])) { - $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s', + $r = q("update xchan set xchan_name = '%s', xchan_name_date = '%s', xchan_connurl = '%s', xchan_follow = '%s', xchan_connpage = '%s', xchan_flags = %d, xchan_addr = '%s', xchan_url = '%s' where xchan_hash = '%s'", dbesc(($arr['name']) ? $arr['name'] : '-'), @@ -754,8 +759,9 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { } else { $import_photos = true; - if((($arr['site']['directory_mode'] === 'standalone') || ($dirmode & DIRECTORY_MODE_STANDALONE)) -&& ($arr['site']['url'] != z_root())) + if((($arr['site']['directory_mode'] === 'standalone') + || ($dirmode & DIRECTORY_MODE_STANDALONE)) + && ($arr['site']['url'] != z_root())) $arr['searchable'] = false; $hidden = (1 - intval($arr['searchable'])); @@ -822,7 +828,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { 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. + // 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' where xchan_hash = '%s'", dbesc($photos[0]), @@ -847,7 +853,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 + // 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); @@ -870,19 +876,18 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { $other_realm = false; $realm = get_directory_realm(); - if(array_key_exists('site',$arr) - && array_key_exists('realm',$arr['site']) + if(array_key_exists('site',$arr) + && array_key_exists('realm',$arr['site']) && (strpos($arr['site']['realm'],$realm) === false)) $other_realm = true; if($dirmode != DIRECTORY_MODE_NORMAL) { // We're some kind of directory server. However we can only add directory information - // if the entry is in the same realm (or is a sub-realm). Sub-realms are denoted by - // including the parent realm in the name. e.g. 'RED_GLOBAL:foo' would allow an entry to + // if the entry is in the same realm (or is a sub-realm). Sub-realms are denoted by + // including the parent realm in the name. e.g. 'RED_GLOBAL:foo' would allow an entry to // be in directories for the local realm (foo) and also the RED_GLOBAL realm. - if(array_key_exists('profile',$arr) && is_array($arr['profile']) && (! $other_realm)) { $profile_changed = import_directory_profile($xchan_hash,$arr['profile'],$address,$ud_flags, 1); if($profile_changed) { @@ -910,7 +915,7 @@ function import_xchan($arr,$ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) { } if(($changed) || ($ud_flags == UPDATE_FLAGS_FORCED)) { - $guid = random_string() . '@' . get_app()->get_hostname(); + $guid = random_string() . '@' . get_app()->get_hostname(); update_modtime($xchan_hash,$guid,$address,$ud_flags); logger('import_xchan: changed: ' . $what,LOGGER_DEBUG); } @@ -987,7 +992,7 @@ function zot_process_response($hub, $arr, $outq) { * * 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. + * 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. * @@ -1028,8 +1033,8 @@ function zot_fetch($arr) { /** * @brief Process incoming array of messages. - * - * Process an incoming array of messages which were obtained via pickup, and + * + * Process an incoming array of messages which were obtained via pickup, and * import, update, delete as directed. * * The message types handled here are 'activity' (e.g. posts), 'mail' , @@ -1051,14 +1056,14 @@ function zot_fetch($arr) { */ function zot_import($arr, $sender_url) { - $data = json_decode($arr['body'],true); + $data = json_decode($arr['body'], true); if(! $data) { logger('zot_import: empty body'); return array(); } - if(array_key_exists('iv',$data)) { + if(array_key_exists('iv', $data)) { $data = json_decode(crypto_unencapsulate($data,get_config('system','prvkey')),true); } @@ -1081,7 +1086,7 @@ function zot_import($arr, $sender_url) { logger('zot_import: notify: ' . print_r($i['notify'],true), LOGGER_DATA); - $hub = zot_gethub($i['notify']['sender']); + $hub = zot_gethub($i['notify']['sender']); if((! $hub) || ($hub['hubloc_url'] != $sender_url)) { logger('zot_import: potential forgery: wrong site for sender: ' . $sender_url . ' != ' . print_r($i['notify'],true)); continue; @@ -1117,16 +1122,16 @@ function zot_import($arr, $sender_url) { continue; } - // It's a specifically targetted post. If we were sent a public_scope hint (likely), - // get rid of it so that it doesn't get stored and cause trouble. + // It's a specifically targetted post. If we were sent a public_scope hint (likely), + // get rid of it so that it doesn't get stored and cause trouble. - if(($i) && is_array($i) && array_key_exists('message',$i) && is_array($i['message']) + if(($i) && is_array($i) && array_key_exists('message',$i) && is_array($i['message']) && $i['message']['type'] === 'activity' && array_key_exists('public_scope',$i['message'])) unset($i['message']['public_scope']); $deliveries = $r; - // We found somebody on this site that's in the recipient list. + // We found somebody on this site that's in the recipient list. } else { @@ -1151,12 +1156,12 @@ function zot_import($arr, $sender_url) { } // if the scope is anything but 'public' we're going to store it as private regardless - // of the private flag on the post. + // of the private flag on the post. - if($i['message'] && array_key_exists('public_scope',$i['message']) + if($i['message'] && array_key_exists('public_scope',$i['message']) && $i['message']['public_scope'] !== 'public') { - if(! array_key_exists('flags',$i['message'])) + if(! array_key_exists('flags',$i['message'])) $i['message']['flags'] = array(); if(! in_array('private',$i['message']['flags'])) $i['message']['flags'][] = 'private'; @@ -1223,7 +1228,7 @@ function zot_import($arr, $sender_url) { logger('Channel sync received: ' . print_r($arr,true), LOGGER_DATA); logger('Channel sync recipients: ' . print_r($deliveries,true), LOGGER_DATA); - + $result = process_channel_sync_delivery($i['notify']['sender'],$arr,$deliveries); } elseif($i['message']['type'] === 'location') { @@ -1231,7 +1236,7 @@ function zot_import($arr, $sender_url) { logger('Location message received: ' . print_r($arr,true), LOGGER_DATA); logger('Location message recipients: ' . print_r($deliveries,true), LOGGER_DATA); - + $result = process_location_delivery($i['notify']['sender'],$arr,$deliveries); } } @@ -1244,19 +1249,18 @@ function zot_import($arr, $sender_url) { 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 -// 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. -// Some of these will be rejected, but this gives us a place to start. - /** * @brief * + * 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 + * 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. + * Some of these will be rejected, but this gives us a place to start. + * * @param array $msg * @return NULL|array */ @@ -1281,24 +1285,24 @@ function public_recips($msg) { // notes (below) from when I got this section of code working. You would think that // we only have to find those with the requisite stream or comment permissions, // depending on whether this is a top-level post or a comment - but you would be wrong. - + // ... so public_recips and allowed_public_recips is working so much better - // than before, but was still not quite right. We seem to be getting all the right - // results for top-level posts now, but comments aren't getting through on channels + // than before, but was still not quite right. We seem to be getting all the right + // results for top-level posts now, but comments aren't getting through on channels // for which we've allowed them to send us their stream, but not comment on our posts. - // The reason is we were seeing if they could comment - and we only need to do that if + // The reason is we were seeing if they could comment - and we only need to do that if // we own the post. If they own the post, we only need to check if they can send us their stream. // if this is a comment and it wasn't sent by the post owner, check to see who is allowing them to comment. - // We should have one specific recipient and this step shouldn't be needed unless somebody stuffed up + // We should have one specific recipient and this step shouldn't be needed unless somebody stuffed up // their software. We may need this step to protect us from bad guys intentionally stuffing up their software. // If it is sent by the post owner, we don't need to do this. We only need to see who is receiving the // owner's stream (which was already set above) - as they control the comment permissions, not us. - // Note that by doing this we introduce another bug because some public forums have channel_w_stream + // Note that by doing this we introduce another bug because some public forums have channel_w_stream // permissions set to themselves only. We also need in this function to add these public forums to the - // public recipient list based on if they are tagged or not and have tag permissions. This is complicated - // by the fact that this activity doesn't have the public forum tag. It's the parent activity that + // public recipient list based on if they are tagged or not and have tag permissions. This is complicated + // by the fact that this activity doesn't have the public forum tag. It's the parent activity that // contains the tag. we'll solve that further below. if($msg['notify']['sender']['guid_sig'] != $msg['message']['owner']['guid_sig']) { @@ -1320,17 +1324,18 @@ function public_recips($msg) { // First find those channels who are accepting posts from anybody, or at least // something greater than just their connections. - if($msg['notify']['sender']['url'] === z_root()) - $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0 - or ( " . $col . " & " . intval(PERMS_SITE) . " ) > 0 - or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0 + if($msg['notify']['sender']['url'] === z_root()) { + $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0 + or ( " . $col . " & " . intval(PERMS_SITE) . " ) > 0 + or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0 or ( " . $col . " & " . intval(PERMS_AUTHED) . ") > 0 ) "; - else - $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0 - or ( " . $col . " & " . intval(PERMS_PUBLIC) . ") > 0 + } else { + $sql = " where (( " . $col . " & " . intval(PERMS_NETWORK) . " ) > 0 + 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' + $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']) ); @@ -1341,13 +1346,13 @@ function public_recips($msg) { // Now we have to get a bit dirty. Find every channel that has the sender in their connections (abook) // and is allowing this sender at least at a high level. - $x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id - where abook_xchan = '%s' and ( channel_pageflags & " . intval(PAGE_REMOVED) . " ) = 0 - and (( " . $col . " & " . intval(PERMS_SPECIFIC) . " ) > 0 and ( abook_my_perms & " . intval($field) . " ) > 0 ) - OR ( " . $col . " & " . intval(PERMS_PENDING) . " ) > 0 + $x = q("select channel_hash as hash from channel left join abook on abook_channel = channel_id + where abook_xchan = '%s' and ( channel_pageflags & " . intval(PAGE_REMOVED) . " ) = 0 + and (( " . $col . " & " . intval(PERMS_SPECIFIC) . " ) > 0 and ( abook_my_perms & " . intval($field) . " ) > 0 ) + OR ( " . $col . " & " . intval(PERMS_PENDING) . " ) > 0 OR (( " . $col . " & " . intval(PERMS_CONTACTS) . " ) > 0 and ( abook_flags & " . intval(ABOOK_FLAG_PENDING) . " ) = 0 ) ", dbesc($msg['notify']['sender']['hash']) - ); + ); if(! $x) $x = array(); @@ -1386,7 +1391,7 @@ function public_recips($msg) { } else { // This is a comment. We need to find any parent with ITEM_UPLINK set. But in fact, let's just return - // everybody that stored a copy of the parent. This way we know we're covered. We'll check the + // everybody that stored a copy of the parent. This way we know we're covered. We'll check the // comment permissions when we deliver them. if($msg['message']['message_top']) { @@ -1395,7 +1400,7 @@ function public_recips($msg) { intval(ITEM_UPLINK) ); if($z) - $r = array_merge($r,$z); + $r = array_merge($r,$z); } } @@ -1404,7 +1409,7 @@ function public_recips($msg) { if($r) { $uniq = array(); - + foreach($r as $rr) { if(! in_array($rr['hash'],$uniq)) $uniq[] = $rr['hash']; @@ -1419,9 +1424,18 @@ function public_recips($msg) { return $r; } -// This is the second part of the above function. We'll find all the channels willing to accept public posts from us, -// then match them against the sender privacy scope and see who in that list that the sender is allowing. - +/** + * @brief + * + * This is the second part of public_recipes(). + * We'll find all the channels willing to accept public posts from us, then + * match them against the sender privacy scope and see who in that list that + * the sender is allowing. + * + * @see public_recipes() + * @param array $msg + * @return array + */ function allowed_public_recips($msg) { logger('allowed_public_recips: ' . print_r($msg,true),LOGGER_DATA); @@ -1431,8 +1445,8 @@ function allowed_public_recips($msg) { // Mail won't have a public scope. // in fact, it's doubtful mail will ever get here since it almost universally - // has a recipient, but in fact we don't require this, so it's technically - // possible to send mail to anybody that's listening. + // has a recipient, but in fact we don't require this, so it's technically + // possible to send mail to anybody that's listening. $recips = public_recips($msg); @@ -1483,12 +1497,21 @@ function allowed_public_recips($msg) { return array(); } - -function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$request = false) { +/** + * @brief + * + * @param array $sender + * @param array $arr + * @param array $deliveries + * @param boolean $relay + * @param boolean $public (optional) default false + * @param boolean $request (optional) default false + * @return array + */ +function process_delivery($sender, $arr, $deliveries, $relay, $public = false, $request = false) { $result = array(); - // We've validated the sender. Now make sure that the sender is the owner or author if(! $public) { @@ -1505,7 +1528,7 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque ); if(! $r) { - $result[] = array($d['hash'],'recipients not found'); + $result[] = array($d['hash'], 'recipients not found'); continue; } @@ -1513,7 +1536,7 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque // allow public postings to the sys channel regardless of permissions, but not // for comments travelling upstream. Wait and catch them on the way down. - // They may have been blocked by the owner. + // They may have been blocked by the owner. if(($channel['channel_pageflags'] & PAGE_SYSTEM) && (! $arr['item_private']) && (! $relay)) { $local_public = true; @@ -1557,7 +1580,7 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque // We are only going to accept comments from this sender if the comment has the same route as the top-level-post, // this is so that permissions mismatches between senders apply to the entire conversation // As a side effect we will also do a preliminary check that we have the top-level-post, otherwise - // processing it is pointless. + // processing it is pointless. $r = q("select route, id from item where mid = '%s' and uid = %d limit 1", dbesc($arr['parent_mid']), @@ -1566,21 +1589,21 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque if(! $r) { $result[] = array($d['hash'],'comment parent not found',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); - // We don't seem to have a copy of this conversation or at least the parent + // We don't seem to have a copy of this conversation or at least the parent // - so request a copy of the entire conversation to date. - // Don't do this if it's a relay post as we're the ones who are supposed to + // Don't do this if it's a relay post as we're the ones who are supposed to // have the copy and we don't want the request to loop. // Also don't do this if this comment came from a conversation request packet. // It's possible that comments are allowed but posting isn't and that could - // cause a conversation fetch loop. We can detect these packets since they are - // delivered via a 'notify' packet type that has a message_id element in the - // initial zot packet (just like the corresponding 'request' packet type which + // cause a conversation fetch loop. We can detect these packets since they are + // delivered via a 'notify' packet type that has a message_id element in the + // initial zot packet (just like the corresponding 'request' packet type which // makes the request). // We'll also check the send_stream permission - because if it isn't allowed, // the top level post is unlikely to be imported and - // this is just an exercise in futility. + // this is just an exercise in futility. - if((! $relay) && (! $request) && (! $local_public) + if((! $relay) && (! $request) && (! $local_public) && perm_is_allowed($channel['channel_id'],$sender['hash'],'send_stream')) { proc_run('php', 'include/notifier.php', 'request', $channel['channel_id'], $sender['hash'], $arr['parent_mid']); } @@ -1598,7 +1621,7 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque // sent it to us originally. Ignore it if it came from another source // (with potentially different permissions). // only compare the last hop since it could have arrived at the last location any number of ways. - // Always accept empty routes and firehose items (route contains 'undefined') . + // Always accept empty routes and firehose items (route contains 'undefined') . $existing_route = explode(',', $r[0]['route']); $routes = count($existing_route); @@ -1610,7 +1633,7 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque $last_hop = ''; $last_prior_route = ''; } - + if(in_array('undefined',$existing_route) || $last_hop == 'undefined' || $sender['hash'] == 'undefined') $last_hop = ''; @@ -1623,7 +1646,7 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque continue; } - // we'll add sender['hash'] onto this when we deliver it. $last_prior_route now has the previously stored route + // we'll add sender['hash'] onto this when we deliver it. $last_prior_route now has the previously stored route // *except* for the sender['hash'] which would've been the last hop before it got to us. $arr['route'] = $last_prior_route; @@ -1661,11 +1684,11 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque // We already have this post. $item_id = $r[0]['id']; if($r[0]['item_restrict'] & ITEM_DELETED) { - // It was deleted locally. + // It was deleted locally. $result[] = array($d['hash'],'update ignored',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); continue; - } - // Maybe it has been edited? + } + // Maybe it has been edited? elseif($arr['edited'] > $r[0]['edited']) { $arr['id'] = $r[0]['id']; $arr['uid'] = $channel['channel_id']; @@ -1676,8 +1699,8 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque } else { $result[] = array($d['hash'],'update ignored',$channel['channel_name'] . ' <' . $channel['channel_address'] . '@' . get_app()->get_hostname() . '>',$arr['mid']); - // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit), - // and at the same time not relay any other relayable posts more than once, because to do so is very wasteful. + // We need this line to ensure wall-to-wall comments are relayed (by falling through to the relay bit), + // and at the same time not relay any other relayable posts more than once, because to do so is very wasteful. if(! ($r[0]['item_flags'] & ITEM_ORIGIN)) continue; } @@ -1689,8 +1712,8 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque // if it's a sourced post, call the post_local hooks as if it were // posted locally so that crosspost connectors will be triggered. - if(check_item_source($arr['uid'],$arr)) - call_hooks('post_local',$arr); + if(check_item_source($arr['uid'], $arr)) + call_hooks('post_local', $arr); $item_result = item_store($arr); $item_id = 0; @@ -1713,17 +1736,27 @@ function process_delivery($sender,$arr,$deliveries,$relay,$public = false,$reque } if(! $deliveries) - $result[] = array('','no recipients','',$arr['mid']); + $result[] = array('', 'no recipients', '', $arr['mid']); - logger('process_delivery: local results: ' . print_r($result,true), LOGGER_DEBUG); + logger('process_delivery: local results: ' . print_r($result, true), LOGGER_DEBUG); return $result; } +/** + * @brief + * + * @param array $sender an associative array with + * * \e string \b hash a xchan_hash + * @param array $arr an associative array + * * \e int \b verb + * * \e int \b obj_type + * * \e int \b mid + * @param int $uid + */ +function remove_community_tag($sender, $arr, $uid) { -function remove_community_tag($sender,$arr,$uid) { - - if(! (activity_match($arr['verb'],ACTIVITY_TAG) && ($arr['obj_type'] == ACTIVITY_OBJ_TAGTERM))) + if(! (activity_match($arr['verb'], ACTIVITY_TAG) && ($arr['obj_type'] == ACTIVITY_OBJ_TAGTERM))) return; logger('remove_community_tag: invoked'); @@ -1780,7 +1813,15 @@ function remove_community_tag($sender,$arr,$uid) { ); } -function update_imported_item($sender,$item,$uid) { +/** + * @brief Just calls item_store_update() and logs result. + * + * @see item_store_update() + * @param array $sender (unused) + * @param array $item + * @param int $uid (unused) + */ +function update_imported_item($sender, $item, $uid) { $x = item_store_update($item); if(! $x['item_id']) @@ -1793,9 +1834,10 @@ function update_imported_item($sender,$item,$uid) { * @brief Deletes an imported item. * * @param array $sender + * * \e string \b hash a xchan_hash * @param array $item * @param int $uid - * @param unknown $relay + * @param boolean $relay * @return boolean|int post_id */ function delete_imported_item($sender, $item, $uid, $relay) { @@ -1819,9 +1861,9 @@ function delete_imported_item($sender, $item, $uid, $relay) { } 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. + // item_store() won't try to deliver any notifications or start delivery chains if this flag is set. // This means we won't end up with potentially even more delivery threads trying to push this delete notification. - // 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. + // 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.'); @@ -1846,10 +1888,10 @@ function delete_imported_item($sender, $item, $uid, $relay) { // This is a bit hackish, but may have to suffice until the notification/delivery loop is optimised // a bit further. We're going to strip the ITEM_ORIGIN on this item if it's a comment, because - // it was already deleted, and we're already relaying, and this ensures that no other process or + // it was already deleted, and we're already relaying, and this ensures that no other process or // 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. + // this information from the metadata should have no other discernible impact. 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", @@ -1858,7 +1900,7 @@ function delete_imported_item($sender, $item, $uid, $relay) { intval($r[0]['uid']) ); } - } + } require_once('include/items.php'); @@ -1872,7 +1914,7 @@ function delete_imported_item($sender, $item, $uid, $relay) { return $post_id; } -function process_mail_delivery($sender,$arr,$deliveries) { +function process_mail_delivery($sender, $arr, $deliveries) { $result = array(); @@ -1898,7 +1940,7 @@ function process_mail_delivery($sender,$arr,$deliveries) { $result[] = array($d['hash'],'permission denied',$channel['channel_name'],$arr['mid']); continue; } - + $r = q("select id from mail where mid = '%s' and channel_id = %d limit 1", dbesc($arr['mid']), intval($channel['channel_id']) @@ -1923,13 +1965,20 @@ function process_mail_delivery($sender,$arr,$deliveries) { $arr['channel_id'] = $channel['channel_id']; $item_id = mail_store($arr); $result[] = array($d['hash'],'mail delivered',$channel['channel_name'],$arr['mid']); - } } + return $result; } -function process_rating_delivery($sender,$arr) { +/** + * @brief Processes delivery of rating. + * + * @param array $sender + * * \e string \b hash a xchan_hash + * @param array $arr + */ +function process_rating_delivery($sender, $arr) { logger('process_rating_delivery: ' . print_r($arr,true)); @@ -1948,8 +1997,8 @@ function process_rating_delivery($sender,$arr) { $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 1 limit 1", dbesc($sender['hash']), dbesc($arr['target']) - ); - + ); + if($r) { if($r[0]['xlink_updated'] >= $arr['edited']) { logger('rating message duplicate'); @@ -1979,8 +2028,16 @@ function process_rating_delivery($sender,$arr) { } } - -function process_profile_delivery($sender,$arr,$deliveries) { +/** + * @brief Processes delivery of profile. + * + * @see import_directory_profile() + * @param array $sender an associative array + * * \e string \b hash a xchan_hash + * @param array $arr + * @param array $deliveries (unused) + */ +function process_profile_delivery($sender, $arr, $deliveries) { logger('process_profile_delivery', LOGGER_DEBUG); @@ -1988,7 +2045,7 @@ function process_profile_delivery($sender,$arr,$deliveries) { dbesc($sender['hash']) ); if($r) - import_directory_profile($sender['hash'],$arr,$r[0]['xchan_addr'], UPDATE_FLAGS_UPDATED, 0); + import_directory_profile($sender['hash'], $arr, $r[0]['xchan_addr'], UPDATE_FLAGS_UPDATED, 0); } function process_location_delivery($sender,$arr,$deliveries) { @@ -2001,23 +2058,31 @@ function process_location_delivery($sender,$arr,$deliveries) { ); if($r) $sender['key'] = $r[0]['xchan_pubkey']; + if(array_key_exists('locations',$arr) && $arr['locations']) { $x = sync_locations($sender,$arr,true); logger('process_location_delivery: results: ' . print_r($x,true), LOGGER_DEBUG); if($x['changed']) { - $guid = random_string() . '@' . get_app()->get_hostname(); + $guid = random_string() . '@' . get_app()->get_hostname(); update_modtime($sender['hash'],$sender['guid'],$arr['locations'][0]['address'],UPDATE_FLAGS_UPDATED); } } } - -function sync_locations($sender,$arr,$absolute = false) { +/** + * @brief Synchronises locations. + * + * @param array $sender + * @param array $arr + * @param boolean $absolute (optional) default false + * @return array + */ +function sync_locations($sender, $arr, $absolute = false) { $ret = array(); if($arr['locations']) { - + $xisting = q("select hubloc_id, hubloc_url, hubloc_sitekey from hubloc where hubloc_hash = '%s'", dbesc($sender['hash']) ); @@ -2045,7 +2110,7 @@ function sync_locations($sender,$arr,$absolute = false) { } for($x = 0; $x < count($xisting); $x ++) { - if(($xisting[$x]['hubloc_url'] === $location['url']) + if(($xisting[$x]['hubloc_url'] === $location['url']) && ($xisting[$x]['hubloc_sitekey'] === $location['sitekey'])) { $xisting[$x]['updated'] = true; } @@ -2061,7 +2126,7 @@ function sync_locations($sender,$arr,$absolute = false) { if(strpos($location['address'],'/') !== false) $location['address'] = substr($location['address'],0,strpos($location['address'],'/')); - // match as many fields as possible in case anything at all changed. + // match as many fields as possible in case anything at all changed. $r = q("select * from hubloc where hubloc_hash = '%s' and hubloc_guid = '%s' and hubloc_guid_sig = '%s' and hubloc_url = '%s' and hubloc_url_sig = '%s' and hubloc_host = '%s' and hubloc_addr = '%s' and hubloc_callback = '%s' and hubloc_sitekey = '%s' ", dbesc($sender['hash']), @@ -2090,7 +2155,7 @@ function sync_locations($sender,$arr,$absolute = false) { ); $current_site = true; } - + // If it is the site we're currently talking to, and it's marked offline, // either we have some bad information - or the thing came back to life. @@ -2110,7 +2175,7 @@ function sync_locations($sender,$arr,$absolute = false) { intval(XCHAN_FLAGS_ORPHAN), dbesc($sender['hash']) ); - } + } // Remove pure duplicates if(count($r) > 1) { @@ -2175,7 +2240,7 @@ function sync_locations($sender,$arr,$absolute = false) { continue; } - // Existing hubs are dealt with. Now let's process any new ones. + // Existing hubs are dealt with. Now let's process any new ones. // New hub claiming to be primary. Make it so by removing any existing primaries. if(intval($location['primary'])) { @@ -2244,9 +2309,9 @@ function sync_locations($sender,$arr,$absolute = false) { * @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 + * @param array $channel an associative array which must contain * * \e string \b channel_hash the hash of the channel - * @return array an array with assoziated arrays + * @return array an array with associative arrays */ function zot_encode_locations($channel) { $ret = array(); @@ -2272,10 +2337,9 @@ function zot_encode_locations($channel) { return $ret; } - /** * @brief Imports a directory profile. - * + * * @param string $hash * @param array $profile * @param string $addr @@ -2319,7 +2383,7 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA $arr['xprof_keywords'] = implode(' ',$clean); // Self censored, make it so - // These are not translated, so the German "erwachsenen" keyword will not censor the directory profile. Only the English form - "adult". + // 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)) { @@ -2333,7 +2397,7 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA dbesc($hash) ); - if ($arr['xprof_age'] > 150) + if ($arr['xprof_age'] > 150) $arr['xprof_age'] = 150; if ($arr['xprof_age'] < 0) $arr['xprof_age'] = 0; @@ -2348,21 +2412,21 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA } } if ($update) { - q("update xprof set - xprof_desc = '%s', - xprof_dob = '%s', - 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' + q("update xprof set + xprof_desc = '%s', + xprof_dob = '%s', + 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' where xprof_hash = '%s'", dbesc($arr['xprof_desc']), dbesc($arr['xprof_dob']), @@ -2412,7 +2476,13 @@ function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLA return $d['update']; } -function import_directory_keywords($hash,$keywords) { +/** + * @brief + * + * @param string $hash + * @param array $keywords + */ +function import_directory_keywords($hash, $keywords) { $existing = array(); $r = q("select * from xtag where xtag_hash = '%s'", @@ -2426,31 +2496,39 @@ function import_directory_keywords($hash,$keywords) { $clean = array(); foreach($keywords as $kw) { - $kw = trim(htmlspecialchars($kw,ENT_COMPAT,'UTF-8',false)); - $kw = trim($kw,','); + $kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false)); + $kw = trim($kw, ','); $clean[] = $kw; } foreach($existing as $x) { - if(! in_array($x,$clean)) + if(! in_array($x, $clean)) $r = q("delete from xtag where xtag_hash = '%s' and xtag_term = '%s'", dbesc($hash), dbesc($x) ); } foreach($clean as $x) { - if(! in_array($x,$existing)) + if(! in_array($x, $existing)) { $r = q("insert into xtag ( xtag_hash, xtag_term) values ( '%s' ,'%s' )", dbesc($hash), dbesc($x) ); + } } } +/** + * @brief + * + * @param string $hash + * @param string $guid + * @param string $addr + * @param int $flags (optional) default 0 + */ +function update_modtime($hash, $guid, $addr, $flags = 0) { -function update_modtime($hash,$guid,$addr,$flags = 0) { - - $dirmode = intval(get_config('system','directory_mode')); + $dirmode = intval(get_config('system', 'directory_mode')); if($dirmode == DIRECTORY_MODE_NORMAL) return; @@ -2473,12 +2551,18 @@ function update_modtime($hash,$guid,$addr,$flags = 0) { } } - -function import_site($arr,$pubkey) { +/** + * @brief + * + * @param array $arr + * @param string $pubkey + * @return boolean true if updated or inserted + */ +function import_site($arr, $pubkey) { if( (! is_array($arr)) || (! $arr['url']) || (! $arr['url_sig'])) return false; - if(! rsa_verify($arr['url'],base64url_decode($arr['url_sig']),$pubkey)) { + if(! rsa_verify($arr['url'], base64url_decode($arr['url_sig']), $pubkey)) { logger('import_site: bad url_sig'); return false; } @@ -2545,11 +2629,11 @@ function import_site($arr,$pubkey) { // Downgrade any others claiming to be primary. As they have // 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()) - && ($arr['url'] != get_directory_primary())) { + if(($site_directory === DIRECTORY_MODE_PRIMARY) + && ($site_realm === get_directory_realm()) + && ($arr['url'] != get_directory_primary())) { $site_directory = DIRECTORY_MODE_NORMAL; - } + } if($exists) { if(($siterecord['site_flags'] != $site_directory) @@ -2614,8 +2698,11 @@ function import_site($arr,$pubkey) { /** * Send a zot packet to all hubs where this channel is duplicated, refreshing * such things as personal settings, channel permissions, address book updates, etc. + * + * @param int $uid + * @param array $packet (optional) default null + * @param boolean $groups_changed (optional) default false */ - function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { $a = get_app(); @@ -2623,7 +2710,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { logger('build_sync_packet'); if($packet) - logger('packet: ' . print_r($packet,true),LOGGER_DATA); + logger('packet: ' . print_r($packet, true),LOGGER_DATA); if(! $uid) $uid = local_channel(); @@ -2651,6 +2738,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { foreach($h as $x) { if($x['hubloc_host'] == $a->get_hostname()) continue; + $synchubs[] = $x; } @@ -2708,10 +2796,9 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { ); if($r) $info['collection_members'] = $r; - } - $interval = ((get_config('system','delivery_interval') !== false) + $interval = ((get_config('system','delivery_interval') !== false) ? intval(get_config('system','delivery_interval')) : 2 ); @@ -2733,13 +2820,21 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) { dbesc(json_encode($info)) ); - proc_run('php','include/deliver.php',$hash); + proc_run('php', 'include/deliver.php', $hash); if($interval) @time_sleep_until(microtime(true) + (float) $interval); } } -function process_channel_sync_delivery($sender,$arr,$deliveries) { +/** + * @brief + * + * @param array $sender + * @param array $arr + * @param array $deliveries + * @return array + */ +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. */ @@ -2784,7 +2879,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { } if(count($clean)) { foreach($clean as $k => $v) { - $r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) + $r = dbq("UPDATE channel set " . dbesc($k) . " = '" . dbesc($v) . "' where channel_id = " . intval($channel['channel_id']) ); } } @@ -2813,7 +2908,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { if($abook['abook_xchan'] && $abook['entry_deleted']) { logger('process_channel_sync_delivery: removing abook entry for ' . $abook['abook_xchan']); require_once('include/Contact.php'); - + $r = q("select abook_id, abook_flags from abook where abook_xchan = '%s' and abook_channel = %d and not ( abook_flags & %d )>0 limit 1", dbesc($abook['abook_xchan']), intval($channel['channel_id']), @@ -2893,8 +2988,8 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { foreach($clean as $k => $v) { if($k == 'abook_dob') $v = dbescdate($v); - - $r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v) + + $r = dbq("UPDATE abook set " . dbesc($k) . " = '" . dbesc($v) . "' where abook_xchan = '" . dbesc($clean['abook_xchan']) . "' and abook_channel = " . intval($channel['channel_id'])); } } @@ -2917,8 +3012,8 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { } } if($found) { - if(($y['name'] != $cl['name']) - || ($y['visible'] != $cl['visible']) + if(($y['name'] != $cl['name']) + || ($y['visible'] != $cl['visible']) || ($y['deleted'] != $cl['deleted'])) { q("update groups set name = '%s', visible = %d, deleted = %d where hash = '%s' and uid = %d", dbesc($cl['name']), @@ -2959,10 +3054,10 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { break; } } - if(! $found_local) { + if(! $found_local) { q("delete from group_member where gid = %d", intval($y['id']) - ); + ); q("update groups set deleted = 1 where id = %d and uid = %d", intval($y['id']), intval($channel['channel_id']) @@ -2979,15 +3074,17 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { // now sync the members - if(array_key_exists('collection_members',$arr) && - is_array($arr['collection_members']) && count($arr['collection_members'])) { + if(array_key_exists('collection_members', $arr) + && is_array($arr['collection_members']) + && count($arr['collection_members'])) { // first sort into groups keyed by the group hash $members = array(); foreach($arr['collection_members'] as $cm) { if(! array_key_exists($cm['collection'],$members)) $members[$cm['collection']] = array(); - $members[$cm['collection']][] = $cm['member']; + + $members[$cm['collection']][] = $cm['member']; } // our group list is already synchronised @@ -3074,7 +3171,7 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { } if(count($clean)) { foreach($clean as $k => $v) { - $r = dbq("UPDATE profile set " . dbesc($k) . " = '" . dbesc($v) + $r = dbq("UPDATE profile set " . dbesc($k) . " = '" . dbesc($v) . "' where profile_guid = '" . dbesc($profile['profile_guid']) . "' and uid = " . intval($channel['channel_id'])); } } @@ -3087,8 +3184,15 @@ function process_channel_sync_delivery($sender,$arr,$deliveries) { return $result; } -// We probably should make rpost discoverable. - +/** + * @brief Returns path to /rpost + * + * @todo We probably should make rpost discoverable. + * + * @param array $observer + * * \e string \b xchan_url + * @return string + */ function get_rpost_path($observer) { if(! $observer) return ''; @@ -3098,7 +3202,6 @@ function get_rpost_path($observer) { return $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '') . '/rpost?f='; } - /** * @brief * @@ -3127,7 +3230,6 @@ function import_author_zot($x) { return false; } - /** * @brief Process a message request. * @@ -3136,10 +3238,10 @@ function import_author_zot($x) { * 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. * - * include/deliver.php (for local delivery) and mod/post.php (for web delivery) detect the existence of - * this 'message_list' at the destination and split it into individual messages which are - * processed/delivered in order. - * + * include/deliver.php (for local delivery) and mod/post.php (for web delivery) detect the existence of + * this 'message_list' at the destination and split it into individual messages which are + * processed/delivered in order. + * * Called from mod/post.php * * @param array $data @@ -3181,7 +3283,7 @@ function zot_process_message_request($data) { if ($messages) { $env_recips = null; - $r = q("select hubloc_guid, hubloc_url, hubloc_sitekey, hubloc_network, hubloc_flags, hubloc_callback, hubloc_host + $r = q("select hubloc_guid, hubloc_url, hubloc_sitekey, hubloc_network, hubloc_flags, hubloc_callback, hubloc_host from hubloc where hubloc_hash = '%s' and not (hubloc_flags & %d)>0 and not (hubloc_status & %d)>0 ", dbesc($sender_hash), @@ -3208,8 +3310,8 @@ function zot_process_message_request($data) { */ $n = zot_build_packet($c[0],'notify',$env_recips,(($private) ? $hub['hubloc_sitekey'] : null),$hash,array('message_id' => $data['message_id'])); - q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, - outq_created, outq_updated, outq_notify, outq_msg ) + q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, + outq_created, outq_updated, outq_notify, outq_msg ) values ( '%s', %d, %d, '%s', '%s', %d, '%s', '%s', '%s', '%s' )", dbesc($hash), intval($c[0]['channel_account_id']), |