diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/RedDAV/RedBrowser.php | 9 | ||||
-rw-r--r-- | include/api.php | 333 | ||||
-rw-r--r-- | include/attach.php | 10 | ||||
-rw-r--r-- | include/bbcode.php | 414 | ||||
-rw-r--r-- | include/comanche.php | 18 | ||||
-rw-r--r-- | include/conversation.php | 13 | ||||
-rw-r--r-- | include/dir_fns.php | 8 | ||||
-rw-r--r-- | include/event.php | 3 | ||||
-rwxr-xr-x | include/items.php | 414 | ||||
-rw-r--r-- | include/js_strings.php | 1 | ||||
-rw-r--r-- | include/menu.php | 66 | ||||
-rw-r--r-- | include/notifier.php | 22 | ||||
-rw-r--r-- | include/permissions.php | 48 | ||||
-rw-r--r-- | include/socgraph.php | 22 | ||||
-rw-r--r-- | include/taxonomy.php | 5 | ||||
-rw-r--r-- | include/text.php | 123 | ||||
-rw-r--r-- | include/widgets.php | 33 | ||||
-rw-r--r-- | include/zot.php | 548 |
18 files changed, 1283 insertions, 807 deletions
diff --git a/include/RedDAV/RedBrowser.php b/include/RedDAV/RedBrowser.php index 56d18ded6..a0330d7cc 100644 --- a/include/RedDAV/RedBrowser.php +++ b/include/RedDAV/RedBrowser.php @@ -271,18 +271,19 @@ class RedBrowser extends DAV\Browser\Plugin { '$nick' => $this->auth->getCurrentUser() )); - get_app()->page['content'] = $html; - load_pdl(get_app()); + $a = get_app(); + $a->page['content'] = $html; + load_pdl($a); $theme_info_file = "view/theme/" . current_theme() . "/php/theme.php"; if (file_exists($theme_info_file)){ require_once($theme_info_file); if (function_exists(str_replace('-', '_', current_theme()) . '_init')) { $func = str_replace('-', '_', current_theme()) . '_init'; - $func(get_app()); + $func($a); } } - construct_page(get_app()); + construct_page($a); } /** diff --git a/include/api.php b/include/api.php index 3ac8ddbda..b9c4c45a4 100644 --- a/include/api.php +++ b/include/api.php @@ -267,40 +267,46 @@ require_once('include/items.php'); * Returns user info array. */ - function api_get_user(&$a, $contact_id = Null){ + function api_get_user(&$a, $contact_id = null, $contact_xchan = null){ global $called_api; $user = null; $extra_query = ""; - if(!is_null($contact_id)){ - $user=$contact_id; - $extra_query = " AND abook_id = %d "; - } - - if(is_null($user) && x($_GET, 'user_id')) { - $user = intval($_GET['user_id']); - $extra_query = " AND abook_id = %d "; - } - if(is_null($user) && x($_GET, 'screen_name')) { - $user = dbesc($_GET['screen_name']); - $extra_query = " AND xchan_addr like '%s@%%' "; - if (api_user()!==false) - $extra_query .= " AND abook_channel = ".intval(api_user()); + if(! is_null($contact_xchan)) { + $user = local_channel(); + $extra_query = " and abook_xchan = '" . dbesc($contact_xchan) . "' "; } + else { + if(!is_null($contact_id)){ + $user=$contact_id; + $extra_query = " AND abook_id = %d "; + } - if (is_null($user) && argc() > (count($called_api)-1)){ - $argid = count($called_api); - list($user, $null) = explode(".",argv($argid)); - if(is_numeric($user)){ - $user = intval($user); + if(is_null($user) && x($_GET, 'user_id')) { + $user = intval($_GET['user_id']); $extra_query = " AND abook_id = %d "; - } else { - $user = dbesc($user); + } + if(is_null($user) && x($_GET, 'screen_name')) { + $user = dbesc($_GET['screen_name']); $extra_query = " AND xchan_addr like '%s@%%' "; - if (api_user() !== false) + if (api_user()!==false) $extra_query .= " AND abook_channel = ".intval(api_user()); } + + if (is_null($user) && argc() > (count($called_api)-1) && (strstr($a->cmd,'/users'))){ + $argid = count($called_api); + list($xx, $null) = explode(".",argv($argid)); + if(is_numeric($xx)){ + $user = intval($xx); + $extra_query = " AND abook_id = %d "; + } else { + $user = dbesc($xx); + $extra_query = " AND xchan_addr like '%s@%%' "; + if (api_user() !== false) + $extra_query .= " AND abook_channel = ".intval(api_user()); + } + } } if (! $user) { @@ -316,11 +322,13 @@ require_once('include/items.php'); logger('api_user: ' . $extra_query . ', user: ' . $user); // user info + $uinfo = q("SELECT * from abook left join xchan on abook_xchan = xchan_hash WHERE 1 $extra_query", $user ); + if (count($uinfo)==0) { return False; } @@ -394,7 +402,7 @@ require_once('include/items.php'); 'utc_offset' => "+00:00", 'time_zone' => 'UTC', //$uinfo[0]['timezone'], 'geo_enabled' => false, - 'statuses_count' => intval($countitms), #XXX: fix me + 'statuses_count' => intval($countitms), //#XXX: fix me 'lang' => get_app()->language, 'description' => (($profile) ? $profile[0]['pdesc'] : ''), 'followers_count' => intval($countfollowers), @@ -410,11 +418,16 @@ require_once('include/items.php'); 'profile_background_tile' => false, 'profile_use_background_image' => false, 'notifications' => false, - 'following' => '', #XXX: fix me - 'verified' => true, #XXX: fix me - 'status' => array() + 'following' => '', // #XXX: fix me + 'verified' => true // #XXX: fix me ); - + + $x = api_get_status($uinfo[0]['xchan_hash']); + if($x) + $ret['status'] = $x; + +// logger('api_get_user: ' . print_r($ret,true)); + return $ret; } @@ -446,12 +459,12 @@ require_once('include/items.php'); 'description' => '', 'profile_image_url' => $item['author']['xchan_photo_m'], 'url' => $item['author']['xchan_url'], - 'protected' => false, # + 'protected' => false, 'followers_count' => 0, 'friends_count' => 0, 'created_at' => '', 'favourites_count' => 0, - 'utc_offset' => 0, #XXX: fix me + 'utc_offset' => 0, // #XXX: fix me 'time_zone' => '', //$uinfo[0]['timezone'], 'statuses_count' => 0, 'following' => 1, @@ -460,7 +473,7 @@ require_once('include/items.php'); 'uid' => 0, 'contact_url' => 0, 'geo_enabled' => false, - 'lang' => 'en', #XXX: fix me + 'lang' => 'en', // #XXX: fix me 'contributors_enabled' => false, 'follow_request_sent' => false, 'profile_background_color' => 'cfe8f6', @@ -471,9 +484,8 @@ require_once('include/items.php'); 'profile_background_image_url' => '', 'profile_background_tile' => false, 'profile_use_background_image' => false, - 'verified' => true, #XXX: fix me - 'followers' => '', #XXX: fix me - 'status' => array() + 'verified' => true, // #XXX: fix me + 'followers' => '' // #XXX: fix me ); return $ret; @@ -667,6 +679,7 @@ require_once('include/items.php'); $a->argv[1] = $user_info['screen_name']; $_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo + $_FILES['userfile'] = $_FILES['media']; require_once('mod/wall_attach.php'); $posted = wall_attach_post($a); @@ -755,8 +768,8 @@ require_once('include/items.php'); $_FILES['userfile'] = $_FILES['media']; // upload the image if we have one $_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo - require_once('mod/wall_upload.php'); - $media = wall_upload_post($a); + require_once('mod/wall_attach.php'); + $media = wall_attach_post($a); if(strlen($media)>0) $_REQUEST['body'] .= "\n\n".$media; } @@ -807,13 +820,65 @@ require_once('include/items.php'); api_register_func('api/red/item/new','red_item_new', true); + function api_get_status($xchan_hash) { + require_once('include/security.php'); + $lastwall = q("SELECT * from item where + item_private = 0 and item_restrict = 0 + and author_xchan = '%s' + and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = '' + and verb = '%s' + order by created desc limit 1", + dbesc($xchan_hash), + dbesc(ACTIVITY_POST) + ); + if($lastwall){ + $lastwall = $lastwall[0]; + + $in_reply_to_status_id = ''; + $in_reply_to_user_id = ''; + $in_reply_to_screen_name = ''; + if($lastwall['author_xchan'] != $lastwall['owner_xchan']) { + $w = q("select * from abook left join xchan on abook_xchan = xchan_hash where + xchan_hash = '%s' limit 1", + dbesc($lastwall['owner_xchan']) + ); + if($w) { + $in_reply_to_user_id = $w[0]['abook_id']; + $in_reply_to_screen_name = substr($w[0]['xchan_addr'],0,strpos($w[0]['xchan_addr'],'@')); + } + } + + if ($lastwall['parent']!=$lastwall['id']) { + $in_reply_to_status_id=$lastwall['thr_parent']; + if(! $in_reply_to_user_id) { + $in_reply_to_user_id = $user_info['id']; + $in_reply_to_screen_name = $user_info['screen_name']; + } + } + unobscure($lastwall); + $status_info = array( + 'text' => html2plain(prepare_text($lastwall['body'],$lastwall['mimetype']), 0), + 'truncated' => false, + 'created_at' => api_date($lastwall['created']), + 'in_reply_to_status_id' => $in_reply_to_status_id, + 'source' => (($lastwall['app']) ? $lastwall['app'] : 'web'), + 'id' => ($lastwall['id']), + 'in_reply_to_user_id' => $in_reply_to_user_id, + 'in_reply_to_screen_name' => $in_reply_to_screen_name, + 'geo' => '', + 'favorited' => false, + 'coordinates' => $lastwall['coord'], + 'place' => $lastwall['location'], + 'contributors' => '' + ); - - - + } + + return $status_info; + } function api_status_show(&$a, $type){ $user_info = api_get_user($a); @@ -827,7 +892,6 @@ require_once('include/items.php'); and author_xchan = '%s' and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = '' and verb = '%s' - and uid in ( " . stream_perms_api_uids() . " ) order by created desc limit 1", dbesc($user_info['guid']), dbesc(ACTIVITY_POST) @@ -901,7 +965,6 @@ require_once('include/items.php'); and author_xchan = '%s' and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = '' and verb = '%s' - and uid in ( " . stream_perms_api_uids() . " ) order by created desc limit 1", dbesc($user_info['guid']), dbesc(ACTIVITY_POST) @@ -1047,8 +1110,8 @@ require_once('include/items.php'); if (api_user()===false) return false; $user_info = api_get_user($a); - // get last newtork messages + $sys = get_sys_channel(); // params $count = (x($_REQUEST,'count')?$_REQUEST['count']:20); @@ -1070,7 +1133,7 @@ require_once('include/items.php'); and allow_cid = '' and allow_gid = '' and deny_cid = '' and deny_gid = '' and item_private = 0 - and uid in ( " . stream_perms_api_uids() . " ) + and uid = " . $sys['channel_id'] . " $sql_extra AND id > %d group by mid order by received desc LIMIT %d OFFSET %d ", @@ -1417,58 +1480,155 @@ require_once('include/items.php'); api_register_func('api/statuses/user_timeline','api_statuses_user_timeline', true); + + /** + * Star/unstar an item + * param: id : id of the item + * + * api v1 : https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid + */ + function api_favorites_create_destroy(&$a, $type){ + + logger('favorites_create_destroy'); + + if (api_user()===false) + return false; + + $action = str_replace(".".$type,"",argv(2)); + if (argc() > 3) { + $itemid = intval(argv(3)); + } else { + $itemid = intval($_REQUEST['id']); + } + + $item = q("SELECT * FROM item WHERE id = %d AND uid = %d", + intval($itemid), + intval(api_user()) + ); + + if (! $item) + return false; + + switch($action){ + case "create": + + $flags = $item[0]['item_flags'] | ITEM_STARRED; + + break; + case "destroy": + + $flags = $item[0]['item_flags'] | (~ ITEM_STARRED); + break; + default: + return false; + } + + $r = q("UPDATE item SET item_flags = %d where id = %d and uid = %d", + intval($flags), + intval($itemid), + intval(api_user()) + ); + if(! $r) + return false; + + $item = q("SELECT * FROM item WHERE id = %d AND uid = %d", + intval($itemid), + intval(api_user()) + ); + + xchan_query($item,true); + + + $user_info = api_get_user($a); + $rets = api_format_items($item,$user_info); + $ret = $rets[0]; + + $data = array('$status' => $ret); + switch($type){ + case "atom": + case "rss": + $data = api_rss_extra($a, $data, $user_info); + } + + return api_apply_template("status", $type, $data); + } + + api_register_func('api/favorites/create', 'api_favorites_create_destroy', true); + api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true); + + + function api_favorites(&$a, $type){ - if (api_user()===false) return false; + if (api_user()===false) + return false; $user_info = api_get_user($a); - // in friendica starred item are private - // return favorites only for self - logger('api_favorites: self:' . $user_info['self']); - if ($user_info['self']==0) { - $ret = array(); - } else { + // params + $count = (x($_REQUEST,'count')?$_REQUEST['count']:20); + $page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0); + if($page < 0) + $page = 0; + $since_id = (x($_REQUEST,'since_id')?$_REQUEST['since_id']:0); + $max_id = (x($_REQUEST,'max_id')?$_REQUEST['max_id']:0); + $exclude_replies = (x($_REQUEST,'exclude_replies')?1:0); + $start = $page*$count; - // params - $count = (x($_GET,'count')?$_GET['count']:20); - $page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0); - if ($page<0) $page=0; - - $start = $page*$count; - - $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, - `contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`, - `contact`.`network`, `contact`.`thumb`, `contact`.`dfrn_id`, `contact`.`self`, - `contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid` - FROM `item`, `contact` - WHERE `item`.`uid` = %d - AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0 - AND `item`.`starred` = 1 - AND `contact`.`id` = `item`.`contact-id` - AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 - $sql_extra - ORDER BY `item`.`received` DESC LIMIT %d ,%d ", - intval($user_info['uid']), - intval($start), intval($count) - ); + //$include_entities = (x($_REQUEST,'include_entities')?$_REQUEST['include_entities']:false); - $ret = api_format_items($r,$user_info); + $sql_extra = ''; + if ($max_id > 0) + $sql_extra .= ' AND `item`.`id` <= '.intval($max_id); + if ($exclude_replies > 0) + $sql_extra .= ' AND `item`.`parent` = `item`.`id`'; + if (api_user() != $user_info['uid']) { + $observer = get_app()->get_observer(); + require_once('include/permissions.php'); + if(! perm_is_allowed($user_info['uid'],(($observer) ? $observer['xchan_hash'] : ''),'view_stream')) + return ''; + $sql_extra .= " and item_private = 0 "; } + $r = q("SELECT * from item WHERE uid = %d and item_restrict = 0 + and ( item_flags & %d ) > 0 $sql_extra + AND id > %d + ORDER BY received DESC LIMIT %d ,%d ", + intval($user_info['uid']), + intval(ITEM_STARRED), + intval($since_id), + intval($start), + intval($count) + ); + + xchan_query($r,true); + + $ret = api_format_items($r,$user_info); + $data = array('$statuses' => $ret); switch($type){ case "atom": case "rss": $data = api_rss_extra($a, $data, $user_info); + break; + case "as": + $as = api_format_as($a, $ret, $user_info); + $as['title'] = $a->config['sitename']." Home Timeline"; + $as['link']['url'] = $a->get_baseurl()."/".$user_info["screen_name"]."/all"; + return($as); + break; } return api_apply_template("timeline", $type, $data); + } api_register_func('api/favorites','api_favorites', true); + + + function api_format_as($a, $ret, $user_info) { $as = array(); @@ -1534,7 +1694,7 @@ require_once('include/items.php'); return($as); } - function api_format_messages($item, $recipient, $sender) { + function api_format_message($item, $recipient, $sender) { // standard meta information $ret = array( 'id' => $item['id'], @@ -1546,7 +1706,7 @@ require_once('include/items.php'); 'recipient_screen_name' => $recipient['screen_name'], 'recipient' => $recipient, ); - unobscure($item); + unobscure_mail($item); //don't send title to regular StatusNET requests to avoid confusing these apps if (x($_GET, 'getText')) { $ret['title'] = $item['title'] ; @@ -1584,6 +1744,8 @@ require_once('include/items.php'); localize_item($item); $status_user = (($item['author_xchan']==$user_info['guid'])?$user_info: api_item_get_user($a,$item)); + if(array_key_exists('status',$status_user)) + unset($status_user['status']); if($item['parent'] != $item['id']) { $r = q("select id from item where parent= %d and id < %d order by id desc limit 1", @@ -1909,7 +2071,7 @@ require_once('include/items.php'); if ($id>-1) { $r = q("SELECT * FROM `mail` WHERE id=%d", intval($id)); - $ret = api_format_messages($r[0], $recipient, $sender); + $ret = api_format_message($r[0], $recipient, $sender); } else { $ret = array("error"=>$id); @@ -1963,18 +2125,16 @@ require_once('include/items.php'); $ret = Array(); if($r) { foreach($r as $item) { - if ($box == "inbox" || $item['from-url'] != $profile_url){ - $recipient = $user_info; - // fixme to lookup recipient - $sender = api_get_user($a); - } - elseif ($box == "sentbox" || $item['from-url'] != $profile_url){ - // fixme to lookup recipient - $recipient = api_get_user($a); + if ($item['from_xchan'] == $channel['channel_hash']) { $sender = $user_info; + $recipient = api_get_user($a, null, $item['to_xchan']); + } + else { + $sender = api_get_user($a, null, $item['from_xchan']); + $recipient = $user_info; } - $ret[]=api_format_messages($item, $recipient, $sender); + $ret[]=api_format_message($item, $recipient, $sender); } } @@ -2040,9 +2200,6 @@ logger('Req: ' . var_export($req,true)); /* Not implemented by now: -favorites -favorites/create -favorites/destroy statuses/retweets_of_me friendships/create friendships/destroy diff --git a/include/attach.php b/include/attach.php index 415859b39..e6d6e5f24 100644 --- a/include/attach.php +++ b/include/attach.php @@ -812,8 +812,8 @@ function attach_delete($channel_id, $resource) { if($y) { $f = 'store/' . $channel_address . '/' . $y[0]['data']; - if(is_dir($f)) - @rmdir($f); + if(is_dir($y[0]['data'])) + @rmdir($y[0]['data']); elseif(file_exists($f)) unlink($f); } @@ -832,7 +832,7 @@ function attach_delete($channel_id, $resource) { intval($channel_id) ); - file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $no_activity=false); + file_activity($channel_id, $object, $object['allow_cid'], $object['allow_gid'], $object['deny_cid'], $object['deny_gid'], 'update', $notify=0); } /** @@ -985,7 +985,7 @@ function pipe_streams($in, $out) { * @param string $verb * @param boolean $no_activity */ -function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $verb, $no_activity) { +function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $verb, $notify) { require_once('include/items.php'); @@ -1107,7 +1107,7 @@ function file_activity($channel_id, $object, $allow_cid, $allow_gid, $deny_cid, //notice( t('File activity updated') . EOL); } - if($no_activity) { + if(! $notify) { return; } diff --git a/include/bbcode.php b/include/bbcode.php index e97a96f87..4ff6f842e 100644 --- a/include/bbcode.php +++ b/include/bbcode.php @@ -1,28 +1,33 @@ -<?php /** @file */ +<?php +/** + * @file include/bbcode.php + * @brief BBCode related functions for parsing, etc. + */ -require_once("include/oembed.php"); +require_once('include/oembed.php'); require_once('include/event.php'); require_once('include/zot.php'); require_once('include/hubloc.php'); function tryoembed($match) { - $url = ((count($match)==2)?$match[1]:$match[2]); + $url = ((count($match) == 2) ? $match[1] : $match[2]); $o = oembed_fetch_url($url); - if ($o->type=="error") return $match[0]; + if ($o->type == 'error') + return $match[0]; $html = oembed_format_object($o); return $html; } function tryzrlaudio($match) { - $link = $match[1]; $zrl = is_matrix_url($link); if($zrl) $link = zid($link); - return '<audio src="' . str_replace(' ','%20',$link) . '" controls="controls" ><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></audio>'; + + return '<audio src="' . str_replace(' ','%20',$link) . '" controls="controls"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></audio>'; } function tryzrlvideo($match) { @@ -30,8 +35,8 @@ function tryzrlvideo($match) { $zrl = is_matrix_url($link); if($zrl) $link = zid($link); - return '<video controls="controls" src="' . str_replace(' ','%20',$link) . '" style="width:100%; max-width:' . get_app()->videowidth . 'px"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></video>'; + return '<video controls="controls" src="' . str_replace(' ','%20',$link) . '" style="width:100%; max-width:' . get_app()->videowidth . 'px"><a href="' . str_replace(' ','%20',$link) . '">' . $link . '</a></video>'; } // [noparse][i]italic[/i][/noparse] turns into @@ -39,11 +44,12 @@ function tryzrlvideo($match) { // to hide them from parser. function bb_spacefy($st) { - $whole_match = $st[0]; - $captured = $st[1]; - $spacefied = preg_replace("/\[(.*?)\]/", "[ $1 ]", $captured); - $new_str = str_replace($captured, $spacefied, $whole_match); - return $new_str; + $whole_match = $st[0]; + $captured = $st[1]; + $spacefied = preg_replace("/\[(.*?)\]/", "[ $1 ]", $captured); + $new_str = str_replace($captured, $spacefied, $whole_match); + + return $new_str; } // The previously spacefied [noparse][ i ]italic[ /i ][/noparse], @@ -51,10 +57,11 @@ function bb_spacefy($st) { // returning [i]italic[/i] function bb_unspacefy_and_trim($st) { - $whole_match = $st[0]; - $captured = $st[1]; - $unspacefied = preg_replace("/\[ (.*?)\ ]/", "[$1]", $captured); - return $unspacefied; + //$whole_match = $st[0]; + $captured = $st[1]; + $unspacefied = preg_replace("/\[ (.*?)\ ]/", "[$1]", $captured); + + return $unspacefied; } @@ -103,8 +110,8 @@ function bb_extract_images($body) { function bb_replace_images($body, $images) { $newbody = $body; - $cnt = 0; + if(! $images) return $newbody; @@ -119,10 +126,15 @@ function bb_replace_images($body, $images) { return $newbody; } - - +/** + * @brief Parses crypt BBCode. + * + * @param array $match + * @return string HTML code + */ function bb_parse_crypt($match) { + $matches = array(); $attributes = $match[1]; $algorithm = ""; @@ -137,7 +149,6 @@ function bb_parse_crypt($match) { $hint = ""; - preg_match("/hint='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") $hint = $matches[1]; @@ -147,36 +158,42 @@ function bb_parse_crypt($match) { $x = random_string(); - $Text = '<br/><div id="' . $x . '"><img src="' . z_root() . '/images/lock_icon.gif" onclick="red_decrypt(\'' . $algorithm . '\',\'' . $hint . '\',\'' . $match[2] . '\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /></div><br />'; + $Text = '<br /><div id="' . $x . '"><img src="' . z_root() . '/images/lock_icon.gif" onclick="red_decrypt(\'' . $algorithm . '\',\'' . $hint . '\',\'' . $match[2] . '\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /></div><br />'; return $Text; - } function bb_parse_app($match) { require_once('include/apps.php'); $app = app_decode($match[1]); - if($app) + if ($app) return app_render($app); - } function bb_parse_element($match) { $j = json_decode(base64url_decode($match[1]),true); - if($j) { + if ($j) { $o = EOL . '<a href="#" onclick="importElement(\'' . $match[1] . '\'); return false;" >' . t('Install design element: ') . $j['pagetitle'] . '</a>' . EOL; } + return $o; } +/** + * @brief Returns an QR-code image from a value given in $match[1]. + * + * @param array $match + * @return string HTML img with QR-code of $match[1] + */ function bb_qr($match) { return '<img class="zrl" src="' . z_root() . '/photo/qr?f=&qr=' . urlencode($match[1]) . '" alt="' . t('QR code') . '" title="' . htmlspecialchars($match[1],ENT_QUOTES,'UTF-8') . '" />'; -} +} function bb_ShareAttributes($match) { + $matches = array(); $attributes = $match[1]; $author = ""; @@ -204,13 +221,14 @@ function bb_ShareAttributes($match) { if ($matches[1] != "") $posted = $matches[1]; + // message_id is never used, do we still need it? $message_id = ""; preg_match("/message_id='(.*?)'/ism", $attributes, $matches); if ($matches[1] != "") $message_id = $matches[1]; - // FIXME - this should really be a wall-item-ago so it will get updated on the client + /** @FIXME - this should really be a wall-item-ago so it will get updated on the client */ $reldate = (($posted) ? relative_date($posted) : ''); $headline = '<div class="shared_container"> <div class="shared_header">'; @@ -230,24 +248,30 @@ function bb_ShareAttributes($match) { $text = $headline . '<div class="reshared-content">' . trim($match[2]) . '</div></div>'; - return($text); + return $text; } function bb_location($match) { // not yet implemented } -function bbiframe($match) { +/** + * @brief Returns an iframe from $match[1]. + * + * @param array $match + * @return string HTML iframe with content of $match[1] + */ +function bb_iframe($match) { $a = get_app(); - - $sandbox = ((strpos($match[1],get_app()->get_hostname())) ? ' sandbox="allow-scripts" ' : ''); + $sandbox = ((strpos($match[1], $a->get_hostname())) ? ' sandbox="allow-scripts" ' : ''); return '<iframe ' . $sandbox . ' src="' . $match[1] . '" width="' . $a->videowidth . '" height="' . $a->videoheight . '"><a href="' . $match[1] . '">' . $match[1] . '</a></iframe>'; } function bb_ShareAttributesSimple($match) { + $matches = array(); $attributes = $match[1]; $author = ""; @@ -268,16 +292,16 @@ function bb_ShareAttributesSimple($match) { if ($matches[1] != "") $profile = $matches[1]; - $text = "<br />".html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8').' <a href="'.$profile.'">'.$author."</a>: div class=\"reshared-content\">" .$match[2]."</div>"; + $text = html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' <a href="' . $profile . '">' . $author . '</a>: div class="reshared-content">' . $match[2] . '</div>'; return($text); } function rpost_callback($match) { if ($match[2]) { - return str_replace($match[0],get_rpost_path(get_app()->get_observer()) . '&title=' . urlencode($match[2]) . '&body=' . urlencode($match[3]),$match[0]); + return str_replace($match[0], get_rpost_path(get_app()->get_observer()) . '&title=' . urlencode($match[2]) . '&body=' . urlencode($match[3]), $match[0]); } else { - return str_replace($match[0],get_rpost_path(get_app()->get_observer()) . '&body=' . urlencode($match[3]),$match[0]); + return str_replace($match[0], get_rpost_path(get_app()->get_observer()) . '&body=' . urlencode($match[3]), $match[0]); } } @@ -291,46 +315,59 @@ function bb_map_location($match) { return str_replace($match[0],'<div class="map" >' . generate_named_map($match[1]) . '</div>', $match[0]); } +function bb_opentag($match) { + $rnd = mt_rand(); + return "<br /><div onclick=\"openClose('opendiv-" . $rnd . "');return false;\" class=\"fakelink\">" . $match[1] . "</div><div id=\"opendiv-" . $rnd . "\" style=\"display: none;\">" . $match[2] . "</div>"; +} +/** + * @brief Sanitize style properties from BBCode to HTML. + * + * @param array $input + * @return string A HTML span tag with the styles. + */ function bb_sanitize_style($input) { - //whitelist property limits (0 = no limitation) - $w = array( // color properties - "color" => 0, - "background-color" => 0, + // whitelist array: property => limits (0 = no limitation) + $w = array( + // color properties + "color" => 0, + "background-color" => 0, // box properties - "padding" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), - "margin" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), - "border" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), - "float" => 0, - "clear" => 0, + "padding" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), + "margin" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), + "border" => array("px"=>100, "%"=>0, "em"=>2, "ex"=>2, "mm"=>0, "cm"=>0, "in"=>0, "pt"=>0, "pc"=>0), + "float" => 0, + "clear" => 0, // text properties - "text-decoration" => 0, - + "text-decoration" => 0, ); + $css = array(); $css_string = $input[1]; - $a = explode(';',$css_string); + $a = explode(';', $css_string); + foreach($a as $parts){ list($k, $v) = explode(':', $parts); - $css[ trim($k) ] = trim($v); + $css[ trim($k) ] = trim($v); } // sanitize properties $b = array_merge(array_diff_key($css, $w), array_diff_key($w, $css)); $css = array_diff_key($css, $b); + $css_string_san = ''; - foreach($css as $key => $value) { - if($w[$key] != null) { - foreach($w[$key] as $limit_key => $limit_value) { + foreach ($css as $key => $value) { + if ($w[$key] != null) { + foreach ($w[$key] as $limit_key => $limit_value) { //sanitize values - if(strpos($value, $limit_key)) { + if (strpos($value, $limit_key)) { $value = preg_replace_callback( "/(\S.*?)$limit_key/ism", function($match) use($limit_value, $limit_key) { - if($match[1] > $limit_value) { + if ($match[1] > $limit_value) { return $limit_value . $limit_key; } else { - return $match[1] . $limit_key; + return $match[1] . $limit_key; } }, $value @@ -340,19 +377,20 @@ function bb_sanitize_style($input) { } $css_string_san .= $key . ":" . $value ."; "; } - return "<span style=\"" . $css_string_san . "\">" . $input[2] . "</span>"; + + return '<span style="' . $css_string_san . '">' . $input[2] . '</span>'; } // BBcode 2 HTML was written by WAY2WEB.net // extended to work with Mistpark/Friendica/Red - Mike Macgirvin -function bbcode($Text,$preserve_nl = false, $tryoembed = true) { +function bbcode($Text, $preserve_nl = false, $tryoembed = true) { $a = get_app(); - // Move all spaces out of the tags + // Move all spaces out of the tags // ....Uhm why? - // This is basically doing a trim() on the stuff in between tags, but it messes up + // This is basically doing a trim() on the stuff in between tags, but it messes up // carefully crafted bbcode and especially other pre-formatted code. // Commenting out until we come up with a use case where it's needed. Then let's try and // special case rather than a heavy-handed approach like this. @@ -382,7 +420,11 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // process [observer] tags before we do anything else because we might // be stripping away stuff that then doesn't need to be worked on anymore - $observer = $a->get_observer(); + if(get_config('system','item_cache')) + $observer = false; + else + $observer = $a->get_observer(); + if ((strpos($Text,'[/observer]') !== false) || (strpos($Text,'[/rpost]') !== false)) { if ($observer) { $Text = preg_replace("/\[observer\=1\](.*?)\[\/observer\]/ism", '$1', $Text); @@ -393,9 +435,13 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $Text = preg_replace("/\[observer\=0\](.*?)\[\/observer\]/ism", '$1', $Text); $Text = preg_replace("/\[rpost(=.*?)?\](.*?)\[\/rpost\]/ism", '', $Text); } - } + } + + if(get_config('system','item_cache')) + $channel = false; + else + $channel = $a->get_channel(); - $channel = $a->get_channel(); if (strpos($Text,'[/channel]') !== false) { if ($channel) { $Text = preg_replace("/\[channel\=1\](.*?)\[\/channel\]/ism", '$1', $Text); @@ -404,7 +450,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $Text = preg_replace("/\[channel\=1\].*?\[\/channel\]/ism", '', $Text); $Text = preg_replace("/\[channel\=0\](.*?)\[\/channel\]/ism", '$1', $Text); } - } + } $x = bb_extract_images($Text); @@ -413,14 +459,14 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $Text = str_replace(array('[baseurl]','[sitename]'),array(z_root(),get_config('system','sitename')),$Text); - + // Replace any html brackets with HTML Entities to prevent executing HTML or script // Don't use strip_tags here because it breaks [url] search by replacing & with amp $Text = str_replace("<", "<", $Text); $Text = str_replace(">", ">", $Text); - + // Convert new line chars to html <br /> tags // nlbr seems to be hopelessly messed up @@ -428,14 +474,14 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // We'll emulate it. - $Text = str_replace("\r\n","\n", $Text); - $Text = str_replace(array("\r","\n"), array('<br />','<br />'), $Text); + $Text = str_replace("\r\n", "\n", $Text); + $Text = str_replace(array("\r", "\n"), array('<br />', '<br />'), $Text); - if($preserve_nl) - $Text = str_replace(array("\n","\r"), array('',''),$Text); + if ($preserve_nl) + $Text = str_replace(array("\n", "\r"), array('', ''), $Text); - $Text = str_replace(array("\t"," "),array(" "," "),$Text); + $Text = str_replace(array("\t", " "), array(" ", " "), $Text); // Set up the parameters for a URL search string $URLSearchString = "^\[\]"; @@ -452,21 +498,19 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $Text = str_replace('[observer.url]',$observer['xchan_url'], $Text); $Text = str_replace('[observer.name]',$s1 . $observer['xchan_name'] . $s2, $Text); $Text = str_replace('[observer.address]',$s1 . $observer['xchan_addr'] . $s2, $Text); - $Text = str_replace('[observer.webname]',$s1 . substr($observer['xchan_addr'],0,strpos($observer['xchan_addr'],'@')) . $s2, $Text); - $Text = str_replace('[observer.photo]',$s1 . '[zmg]'.$observer['xchan_photo_l'].'[/zmg]' . $s2, $Text); + $Text = str_replace('[observer.webname]', substr($observer['xchan_addr'],0,strpos($observer['xchan_addr'],'@')), $Text); + $Text = str_replace('[observer.photo]',$s1 . '[zmg]'.$observer['xchan_photo_l'].'[/zmg]' . $s2, $Text); } else { $Text = str_replace('[observer.baseurl]', '', $Text); $Text = str_replace('[observer.url]','', $Text); $Text = str_replace('[observer.name]','', $Text); $Text = str_replace('[observer.address]','', $Text); $Text = str_replace('[observer.webname]','',$Text); - $Text = str_replace('[observer.photo]','', $Text); + $Text = str_replace('[observer.photo]','', $Text); } - - // Perform URL Search $urlchars = '[a-zA-Z0-9\:\/\-\?\&\;\.\=\@\_\~\#\%\$\!\+\,\@]'; @@ -476,32 +520,31 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { } if (strpos($Text,'[/qr]') !== false) { - $Text = preg_replace_callback("/\[qr\](.*?)\[\/qr\]/ism","bb_qr",$Text); + $Text = preg_replace_callback("/\[qr\](.*?)\[\/qr\]/ism", 'bb_qr', $Text); } - if (strpos($Text,'[/share]') !== false) { - $Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism","bb_ShareAttributes",$Text); + $Text = preg_replace_callback("/\[share(.*?)\](.*?)\[\/share\]/ism", 'bb_ShareAttributes', $Text); } if($tryoembed) { if (strpos($Text,'[/url]') !== false) { - $Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism",'tryoembed',$Text); + $Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism", 'tryoembed', $Text); } - } + } if (strpos($Text,'[/url]') !== false) { - $Text = preg_replace("/\#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" >$1</a>', $Text); + $Text = preg_replace("/\#\^\[url\]([$URLSearchString]*)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" >$1</a>', $Text); $Text = preg_replace("/\#\^\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<span class="bookmark-identifier">#^</span><a class="bookmark" href="$1" >$2</a>', $Text); $Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" >$1</a>', $Text); $Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" >$2</a>', $Text); - } + } if (strpos($Text,'[/zrl]') !== false) { - $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" >$1</a>', $Text); - $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" >$2</a>', $Text); + $Text = preg_replace("/\#\^\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" >$1</a>', $Text); + $Text = preg_replace("/\#\^\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<span class="bookmark-identifier">#^</span><a class="zrl bookmark" href="$1" >$2</a>', $Text); $Text = preg_replace("/\[zrl\]([$URLSearchString]*)\[\/zrl\]/ism", '<a class="zrl" href="$1" >$1</a>', $Text); $Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '<a class="zrl" href="$1" >$2</a>', $Text); - } + } // Perform MAIL Search - if (strpos($Text,'[/mail]') !== false) { + if (strpos($Text,'[/mail]') !== false) { $Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '<a href="mailto:$1">$1</a>', $Text); $Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '<a href="mailto:$1">$2</a>', $Text); } @@ -509,54 +552,52 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // leave open the posibility of [map=something] // this is replaced in prepare_body() which has knowledge of the item location - if (strpos($Text,'[/map]') !== false) { - $Text = preg_replace_callback("/\[map\](.*?)\[\/map\]/ism",'bb_map_location',$Text); + if (strpos($Text,'[/map]') !== false) { + $Text = preg_replace_callback("/\[map\](.*?)\[\/map\]/ism", 'bb_map_location', $Text); } - - if (strpos($Text,'[map=') !== false) { - $Text = preg_replace_callback("/\[map=(.*?)\]/ism",'bb_map_coords',$Text); + if (strpos($Text,'[map=') !== false) { + $Text = preg_replace_callback("/\[map=(.*?)\]/ism", 'bb_map_coords', $Text); } - - if (strpos($Text,'[map]') !== false) { + if (strpos($Text,'[map]') !== false) { $Text = preg_replace("/\[map\]/", '<div class="map"></div>', $Text); } // Check for bold text - if (strpos($Text,'[b]') !== false) { - $Text = preg_replace("(\[b\](.*?)\[\/b\])ism",'<strong>$1</strong>',$Text); + if (strpos($Text,'[b]') !== false) { + $Text = preg_replace("(\[b\](.*?)\[\/b\])ism", '<strong>$1</strong>', $Text); } // Check for Italics text - if (strpos($Text,'[i]') !== false) { - $Text = preg_replace("(\[i\](.*?)\[\/i\])ism",'<em>$1</em>',$Text); + if (strpos($Text,'[i]') !== false) { + $Text = preg_replace("(\[i\](.*?)\[\/i\])ism", '<em>$1</em>', $Text); } // Check for Underline text - if (strpos($Text,'[u]') !== false) { - $Text = preg_replace("(\[u\](.*?)\[\/u\])ism",'<u>$1</u>',$Text); + if (strpos($Text,'[u]') !== false) { + $Text = preg_replace("(\[u\](.*?)\[\/u\])ism", '<u>$1</u>', $Text); } // Check for strike-through text if (strpos($Text,'[s]') !== false) { - $Text = preg_replace("(\[s\](.*?)\[\/s\])ism",'<strike>$1</strike>',$Text); + $Text = preg_replace("(\[s\](.*?)\[\/s\])ism", '<strike>$1</strike>', $Text); } // Check for over-line text - if (strpos($Text,'[o]') !== false) { - $Text = preg_replace("(\[o\](.*?)\[\/o\])ism",'<span class="overline">$1</span>',$Text); + if (strpos($Text,'[o]') !== false) { + $Text = preg_replace("(\[o\](.*?)\[\/o\])ism", '<span class="overline">$1</span>', $Text); } - if (strpos($Text,'[sup]') !== false) { - $Text = preg_replace("(\[sup\](.*?)\[\/sup\])ism",'<sup>$1</sup>',$Text); + if (strpos($Text,'[sup]') !== false) { + $Text = preg_replace("(\[sup\](.*?)\[\/sup\])ism", '<sup>$1</sup>', $Text); } - if (strpos($Text,'[sub]') !== false) { - $Text = preg_replace("(\[sub\](.*?)\[\/sub\])ism",'<sub>$1</sub>',$Text); + if (strpos($Text,'[sub]') !== false) { + $Text = preg_replace("(\[sub\](.*?)\[\/sub\])ism", '<sub>$1</sub>', $Text); } - + // Check for colored text - if (strpos($Text,'[/color]') !== false) { - $Text = preg_replace("(\[color=(.*?)\](.*?)\[\/color\])ism","<span style=\"color: $1;\">$2</span>",$Text); + if (strpos($Text,'[/color]') !== false) { + $Text = preg_replace("(\[color=(.*?)\](.*?)\[\/color\])ism", "<span style=\"color: $1;\">$2</span>", $Text); } // Check for sized text - // [size=50] --> font-size: 50px (with the unit). - if (strpos($Text,'[/size]') !== false) { - $Text = preg_replace("(\[size=(\d*?)\](.*?)\[\/size\])ism","<span style=\"font-size: $1px;\">$2</span>",$Text); - $Text = preg_replace("(\[size=(.*?)\](.*?)\[\/size\])ism","<span style=\"font-size: $1;\">$2</span>",$Text); + // [size=50] --> font-size: 50px (with the unit). + if (strpos($Text,'[/size]') !== false) { + $Text = preg_replace("(\[size=(\d*?)\](.*?)\[\/size\])ism", "<span style=\"font-size: $1px;\">$2</span>", $Text); + $Text = preg_replace("(\[size=(.*?)\](.*?)\[\/size\])ism", "<span style=\"font-size: $1;\">$2</span>", $Text); } // Check for h1 if (strpos($Text,'[h1]') !== false) { @@ -584,16 +625,15 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { } // Check for table of content without params if (strpos($Text,'[toc]') !== false) { - $Text = preg_replace("/\[toc\]/ism",'<ul id="toc"></ul>',$Text); + $Text = preg_replace("/\[toc\]/ism",'<ul id="toc"></ul>',$Text); } // Check for table of content with params if (strpos($Text,'[toc') !== false) { $Text = preg_replace("/\[toc([^\]]+?)\]/ism",'<ul$1></ul>',$Text); - } // Check for centered text - if (strpos($Text,'[/center]') !== false) { - $Text = preg_replace("(\[center\](.*?)\[\/center\])ism","<div style=\"text-align:center;\">$1</div>",$Text); + if (strpos($Text,'[/center]') !== false) { + $Text = preg_replace("(\[center\](.*?)\[\/center\])ism", "<div style=\"text-align:center;\">$1</div>", $Text); } // Check for list text $Text = str_replace("[*]", "<li>", $Text); @@ -602,52 +642,54 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $endlessloop = 0; while ((((strpos($Text, "[/list]") !== false) && (strpos($Text, "[list") !== false)) || - ((strpos($Text, "[/ol]") !== false) && (strpos($Text, "[ol]") !== false)) || - ((strpos($Text, "[/ul]") !== false) && (strpos($Text, "[ul]") !== false)) || - ((strpos($Text, "[/li]") !== false) && (strpos($Text, "[li]") !== false))) && (++$endlessloop < 20)) { - $Text = preg_replace("/\[list\](.*?)\[\/list\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>' ,$Text); - $Text = preg_replace("/\[list=\](.*?)\[\/list\]/ism", '<ul class="listnone" style="list-style-type: none;">$1</ul>' ,$Text); - $Text = preg_replace("/\[list=1\](.*?)\[\/list\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>' ,$Text); - $Text = preg_replace("/\[list=((?-i)i)\](.*?)\[\/list\]/ism",'<ul class="listlowerroman" style="list-style-type: lower-roman;">$2</ul>' ,$Text); - $Text = preg_replace("/\[list=((?-i)I)\](.*?)\[\/list\]/ism", '<ul class="listupperroman" style="list-style-type: upper-roman;">$2</ul>' ,$Text); - $Text = preg_replace("/\[list=((?-i)a)\](.*?)\[\/list\]/ism", '<ul class="listloweralpha" style="list-style-type: lower-alpha;">$2</ul>' ,$Text); - $Text = preg_replace("/\[list=((?-i)A)\](.*?)\[\/list\]/ism", '<ul class="listupperalpha" style="list-style-type: upper-alpha;">$2</ul>' ,$Text); - $Text = preg_replace("/\[ul\](.*?)\[\/ul\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>' ,$Text); - $Text = preg_replace("/\[ol\](.*?)\[\/ol\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>' ,$Text); - $Text = preg_replace("/\[li\](.*?)\[\/li\]/ism", '<li>$1</li>' ,$Text); - } - if (strpos($Text,'[th]') !== false) { - $Text = preg_replace("/\[th\](.*?)\[\/th\]/sm", '<th>$1</th>' ,$Text); + ((strpos($Text, "[/ol]") !== false) && (strpos($Text, "[ol]") !== false)) || + ((strpos($Text, "[/ul]") !== false) && (strpos($Text, "[ul]") !== false)) || + ((strpos($Text, "[/li]") !== false) && (strpos($Text, "[li]") !== false))) && (++$endlessloop < 20)) { + $Text = preg_replace("/\[list\](.*?)\[\/list\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>', $Text); + $Text = preg_replace("/\[list=\](.*?)\[\/list\]/ism", '<ul class="listnone" style="list-style-type: none;">$1</ul>', $Text); + $Text = preg_replace("/\[list=1\](.*?)\[\/list\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>', $Text); + $Text = preg_replace("/\[list=((?-i)i)\](.*?)\[\/list\]/ism",'<ul class="listlowerroman" style="list-style-type: lower-roman;">$2</ul>', $Text); + $Text = preg_replace("/\[list=((?-i)I)\](.*?)\[\/list\]/ism", '<ul class="listupperroman" style="list-style-type: upper-roman;">$2</ul>', $Text); + $Text = preg_replace("/\[list=((?-i)a)\](.*?)\[\/list\]/ism", '<ul class="listloweralpha" style="list-style-type: lower-alpha;">$2</ul>', $Text); + $Text = preg_replace("/\[list=((?-i)A)\](.*?)\[\/list\]/ism", '<ul class="listupperalpha" style="list-style-type: upper-alpha;">$2</ul>', $Text); + $Text = preg_replace("/\[ul\](.*?)\[\/ul\]/ism", '<ul class="listbullet" style="list-style-type: circle;">$1</ul>', $Text); + $Text = preg_replace("/\[ol\](.*?)\[\/ol\]/ism", '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>', $Text); + $Text = preg_replace("/\[li\](.*?)\[\/li\]/ism", '<li>$1</li>', $Text); + } + if (strpos($Text,'[th]') !== false) { + $Text = preg_replace("/\[th\](.*?)\[\/th\]/sm", '<th>$1</th>', $Text); } if (strpos($Text,'[td]') !== false) { - $Text = preg_replace("/\[td\](.*?)\[\/td\]/sm", '<td>$1</td>' ,$Text); + $Text = preg_replace("/\[td\](.*?)\[\/td\]/sm", '<td>$1</td>', $Text); } - if (strpos($Text,'[tr]') !== false) { - $Text = preg_replace("/\[tr\](.*?)\[\/tr\]/sm", '<tr>$1</tr>' ,$Text); + if (strpos($Text,'[tr]') !== false) { + $Text = preg_replace("/\[tr\](.*?)\[\/tr\]/sm", '<tr>$1</tr>', $Text); } - if (strpos($Text,'[/table]') !== false) { - $Text = preg_replace("/\[table\](.*?)\[\/table\]/sm", '<table>$1</table>' ,$Text); - $Text = preg_replace("/\[table border=1\](.*?)\[\/table\]/sm", '<table border="1" >$1</table>' ,$Text); - $Text = preg_replace("/\[table border=0\](.*?)\[\/table\]/sm", '<table border="0" >$1</table>' ,$Text); + if (strpos($Text,'[/table]') !== false) { + $Text = preg_replace("/\[table\](.*?)\[\/table\]/sm", '<table>$1</table>', $Text); + $Text = preg_replace("/\[table border=1\](.*?)\[\/table\]/sm", '<table border="1" >$1</table>', $Text); + $Text = preg_replace("/\[table border=0\](.*?)\[\/table\]/sm", '<table border="0" >$1</table>', $Text); } - $Text = str_replace('</tr><br /><tr>',"</tr>\n<tr>",$Text); - $Text = str_replace('[hr]','<hr />', $Text); + $Text = str_replace('</tr><br /><tr>', "</tr>\n<tr>", $Text); + $Text = str_replace('[hr]', '<hr />', $Text); // This is actually executed in prepare_body() - $Text = str_replace('[nosmile]','',$Text); + $Text = str_replace('[nosmile]', '', $Text); // Check for font change text - if (strpos($Text,'[/font]') !== false) { - $Text = preg_replace("/\[font=(.*?)\](.*?)\[\/font\]/sm","<span style=\"font-family: $1;\">$2</span>",$Text); + if (strpos($Text,'[/font]') !== false) { + $Text = preg_replace("/\[font=(.*?)\](.*?)\[\/font\]/sm", "<span style=\"font-family: $1;\">$2</span>", $Text); } - // Declare the format for [code] layout + // Declare the format for [code] layout $CodeLayout = '<code>$1</code>'; + // Check for [code] text - if (strpos($Text,'[code]') !== false) { - $Text = preg_replace("/\[code\](.*?)\[\/code\]/ism","$CodeLayout", $Text); + if (strpos($Text,'[code]') !== false) { + $Text = preg_replace("/\[code\](.*?)\[\/code\]/ism", "$CodeLayout", $Text); } + // Declare the format for [spoiler] layout $SpoilerLayout = '<blockquote class="spoiler">$1</blockquote>'; @@ -655,7 +697,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // handle nested quotes $endlessloop = 0; while ((strpos($Text, "[/spoiler]") !== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20)) - $Text = preg_replace("/\[spoiler\](.*?)\[\/spoiler\]/ism","$SpoilerLayout", $Text); + $Text = preg_replace("/\[spoiler\](.*?)\[\/spoiler\]/ism", "$SpoilerLayout", $Text); // Check for [spoiler=Author] text @@ -671,14 +713,10 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $endlessloop = 0; while ((strpos($Text, "[/open]")!== false) and (strpos($Text, "[open=") !== false) and (++$endlessloop < 20)) { - $rnd = mt_rand(); - $Text = preg_replace("/\[open=(.*?)\](.*?)\[\/open\]/ism", - "<br /><div onclick=\"openClose('opendiv-" . $rnd . "');return false;\" class=\"fakelink\">$1</div><div id=\"opendiv-" . $rnd . "\" style=\"display: none;\">$2</div>", - $Text); + $Text = preg_replace_callback("/\[open=(.*?)\](.*?)\[\/open\]/ism", 'bb_opentag', $Text); } - // Declare the format for [quote] layout $QuoteLayout = '<blockquote>$1</blockquote>'; @@ -686,7 +724,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // handle nested quotes $endlessloop = 0; while ((strpos($Text, "[/quote]") !== false) and (strpos($Text, "[quote]") !== false) and (++$endlessloop < 20)) - $Text = preg_replace("/\[quote\](.*?)\[\/quote\]/ism","$QuoteLayout", $Text); + $Text = preg_replace("/\[quote\](.*?)\[\/quote\]/ism", "$QuoteLayout", $Text); // Check for [quote=Author] text @@ -750,9 +788,9 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { } // crypt - if (strpos($Text,'[/crypt]') !== false) { + if (strpos($Text,'[/crypt]') !== false) { $x = random_string(); - $Text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism",'<br/><div id="' . $x . '"><img src="' .$a->get_baseurl() . '/images/lock_icon.gif" onclick="red_decrypt(\'rot13\',\'\',\'$1\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /><br /></div>', $Text); + $Text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism",'<br /><div id="' . $x . '"><img src="' .$a->get_baseurl() . '/images/lock_icon.gif" onclick="red_decrypt(\'rot13\',\'\',\'$1\',\'#' . $x . '\');" alt="' . t('Encrypted content') . '" title="' . t('Encrypted content') . '" /><br /></div>', $Text); $Text = preg_replace_callback("/\[crypt (.*?)\](.*?)\[\/crypt\]/ism", 'bb_parse_crypt', $Text); } @@ -764,32 +802,30 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $Text = preg_replace_callback("/\[element\](.*?)\[\/element\]/ism",'bb_parse_element', $Text); } - // html5 video and audio - if (strpos($Text,'[/video]') !== false) { + if (strpos($Text,'[/video]') !== false) { $Text = preg_replace_callback("/\[video\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg))\[\/video\]/ism", 'tryzrlvideo', $Text); } - if (strpos($Text,'[/audio]') !== false) { + if (strpos($Text,'[/audio]') !== false) { $Text = preg_replace_callback("/\[audio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3|opus))\[\/audio\]/ism", 'tryzrlaudio', $Text); } - if (strpos($Text,'[/zvideo]') !== false) { + if (strpos($Text,'[/zvideo]') !== false) { $Text = preg_replace_callback("/\[zvideo\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg))\[\/zvideo\]/ism", 'tryzrlvideo', $Text); } - if (strpos($Text,'[/zaudio]') !== false) { + if (strpos($Text,'[/zaudio]') !== false) { $Text = preg_replace_callback("/\[zaudio\](.*?\.(ogg|ogv|oga|ogm|webm|mp4|mp3|opus))\[\/zaudio\]/ism", 'tryzrlaudio', $Text); } // Try to Oembed if ($tryoembed) { - - if (strpos($Text,'[/video]') !== false) { + if (strpos($Text,'[/video]') !== false) { $Text = preg_replace_callback("/\[video\](.*?)\[\/video\]/ism", 'tryoembed', $Text); } if (strpos($Text,'[/audio]') !== false) { $Text = preg_replace_callback("/\[audio\](.*?)\[\/audio\]/ism", 'tryoembed', $Text); } - if (strpos($Text,'[/zvideo]') !== false) { + if (strpos($Text,'[/zvideo]') !== false) { $Text = preg_replace_callback("/\[zvideo\](.*?)\[\/zvideo\]/ism", 'tryoembed', $Text); } if (strpos($Text,'[/zaudio]') !== false) { @@ -812,43 +848,40 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { $Text = preg_replace("/\[zaudio\](.*?)\[\/zaudio\]/", '<a class="zid" href="$1">$1</a>', $Text); } - - - if ($tryoembed){ if (strpos($Text,'[/iframe]') !== false) { - $Text = preg_replace_callback("/\[iframe\](.*?)\[\/iframe\]/ism", 'bbiframe', $Text); + $Text = preg_replace_callback("/\[iframe\](.*?)\[\/iframe\]/ism", 'bb_iframe', $Text); } - } - else { + } else { if (strpos($Text,'[/iframe]') !== false) { $Text = preg_replace("/\[iframe\](.*?)\[\/iframe\]/ism", '<a href="$1">$1</a>', $Text); } } + // Youtube extensions if (strpos($Text,'[youtube]') !== false) { if ($tryoembed) { - $Text = preg_replace_callback("/\[youtube\](https?:\/\/www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text); - $Text = preg_replace_callback("/\[youtube\](www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text); - $Text = preg_replace_callback("/\[youtube\](https?:\/\/youtu.be\/.*?)\[\/youtube\]/ism",'tryoembed',$Text); + $Text = preg_replace_callback("/\[youtube\](https?:\/\/www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text); + $Text = preg_replace_callback("/\[youtube\](www.youtube.com\/watch\?v\=.*?)\[\/youtube\]/ism", 'tryoembed', $Text); + $Text = preg_replace_callback("/\[youtube\](https?:\/\/youtu.be\/.*?)\[\/youtube\]/ism", 'tryoembed', $Text); } - $Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/youtube\]/ism",'[youtube]$1[/youtube]',$Text); - $Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/embed\/(.*?)\[\/youtube\]/ism",'[youtube]$1[/youtube]',$Text); - $Text = preg_replace("/\[youtube\]https?:\/\/youtu.be\/(.*?)\[\/youtube\]/ism",'[youtube]$1[/youtube]',$Text); + $Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text); + $Text = preg_replace("/\[youtube\]https?:\/\/www.youtube.com\/embed\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text); + $Text = preg_replace("/\[youtube\]https?:\/\/youtu.be\/(.*?)\[\/youtube\]/ism", '[youtube]$1[/youtube]', $Text); if ($tryoembed) - $Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="http://www.youtube.com/embed/$1" frameborder="0" ></iframe>', $Text); - else + $Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="http://www.youtube.com/embed/$1" frameborder="0"></iframe>', $Text); + else $Text = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism", "http://www.youtube.com/watch?v=$1", $Text); } if (strpos($Text,'[vimeo]') !== false) { if ($tryoembed) { - $Text = preg_replace_callback("/\[vimeo\](https?:\/\/player.vimeo.com\/video\/[0-9]+).*?\[\/vimeo\]/ism",'tryoembed',$Text); - $Text = preg_replace_callback("/\[vimeo\](https?:\/\/vimeo.com\/[0-9]+).*?\[\/vimeo\]/ism",'tryoembed',$Text); + $Text = preg_replace_callback("/\[vimeo\](https?:\/\/player.vimeo.com\/video\/[0-9]+).*?\[\/vimeo\]/ism", 'tryoembed', $Text); + $Text = preg_replace_callback("/\[vimeo\](https?:\/\/vimeo.com\/[0-9]+).*?\[\/vimeo\]/ism", 'tryoembed', $Text); } - $Text = preg_replace("/\[vimeo\]https?:\/\/player.vimeo.com\/video\/([0-9]+)(.*?)\[\/vimeo\]/ism",'[vimeo]$1[/vimeo]',$Text); - $Text = preg_replace("/\[vimeo\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/vimeo\]/ism",'[vimeo]$1[/vimeo]',$Text); + $Text = preg_replace("/\[vimeo\]https?:\/\/player.vimeo.com\/video\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $Text); + $Text = preg_replace("/\[vimeo\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/vimeo\]/ism", '[vimeo]$1[/vimeo]', $Text); if ($tryoembed) $Text = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism", '<iframe width="' . $a->videowidth . '" height="' . $a->videoheight . '" src="http://player.vimeo.com/video/$1" frameborder="0" ></iframe>', $Text); @@ -867,7 +900,7 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // Summary (e.g. title) is required, earlier revisions only required description (in addition to // start which is always required). Allow desc with a missing summary for compatibility. - if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) { + if ((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) { $sub = format_event_html($ev); $Text = preg_replace("/\[event\-summary\](.*?)\[\/event\-summary\]/ism",'',$Text); @@ -881,26 +914,25 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true) { // Unhide all [noparse] contained bbtags unspacefying them // and triming the [noparse] tag. if (strpos($Text,'[noparse]') !== false) { - $Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_unspacefy_and_trim',$Text); + $Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_unspacefy_and_trim', $Text); } if (strpos($Text,'[nobb]') !== false) { - $Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_unspacefy_and_trim',$Text); + $Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_unspacefy_and_trim', $Text); } if (strpos($Text,'[pre]') !== false) { - $Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_unspacefy_and_trim',$Text); + $Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_unspacefy_and_trim', $Text); } - $Text = preg_replace('/\[\&\;([#a-z0-9]+)\;\]/','&$1;',$Text); + $Text = preg_replace('/\[\&\;([#a-z0-9]+)\;\]/', '&$1;', $Text); // fix any escaped ampersands that may have been converted into links - $Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism",'<$1$2=$3&$4>',$Text); + $Text = preg_replace("/\<(.*?)(src|href)=(.*?)\&\;(.*?)\>/ism", '<$1$2=$3&$4>', $Text); - $Text = preg_replace("/\<(.*?)(src|href)=\"[^zhfm#](.*?)\>/ism",'<$1$2="">',$Text); + $Text = preg_replace("/\<(.*?)(src|href)=\"[^zhfm#](.*?)\>/ism", '<$1$2="">', $Text); - $Text = bb_replace_images($Text,$saved_images); + $Text = bb_replace_images($Text, $saved_images); - call_hooks('bbcode',$Text); + call_hooks('bbcode', $Text); return $Text; } - diff --git a/include/comanche.php b/include/comanche.php index 62bfd0ddc..c1a98ed6c 100644 --- a/include/comanche.php +++ b/include/comanche.php @@ -133,7 +133,19 @@ function comanche_get_channel_id() { return $channel_id; } -function comanche_block($name) { +function comanche_block($s) { + $var = array(); + $matches = array(); + $name = $s; + + $cnt = preg_match_all("/\[var=(.*?)\](.*?)\[\/var\]/ism", $s, $matches, PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + $var[$mtch[1]] = $mtch[2]; + $name = str_replace($mtch[0], '', $name); + } + } + $o = ''; $channel_id = comanche_get_channel_id(); @@ -143,12 +155,12 @@ function comanche_block($name) { dbesc($name) ); if($r) { - $o = '<div class="widget bblock">'; + $o .= (($var['wrap'] == 'none') ? '' : '<div class="bblock widget">'); if($r[0]['title']) $o .= '<h3>' . $r[0]['title'] . '</h3>'; $o .= prepare_text($r[0]['body'], $r[0]['mimetype']); - $o .= '</div>'; + $o .= (($var['wrap'] == 'none') ? '' : '</div>'); } } diff --git a/include/conversation.php b/include/conversation.php index 67f3afde0..fb012667e 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1095,6 +1095,8 @@ function status_editor($a, $x, $popup = false) { // $plaintext = false; $voting = feature_enabled(local_channel(), 'consensus_tools'); + if(x($x, 'novoting')) + $voting = false; $mimeselect = ''; if(array_key_exists('mimetype', $x) && $x['mimetype']) { @@ -1171,7 +1173,7 @@ function status_editor($a, $x, $popup = false) { '$action' => $a->get_baseurl(true) . '/item', '$share' => (x($x,'button') ? $x['button'] : t('Share')), '$webpage' => $webpage, - '$placeholdpagetitle' => ((x($x,'ptlabel')) ? $x['ptlabel'] : t('Page link title')), + '$placeholdpagetitle' => ((x($x,'ptlabel')) ? $x['ptlabel'] : t('Page link name')), '$pagetitle' => (x($x,'pagetitle') ? $x['pagetitle'] : ''), '$id_select' => $id_select, '$id_seltext' => t('Post as'), @@ -1199,7 +1201,8 @@ function status_editor($a, $x, $popup = false) { '$noloc' => ((get_pconfig($x['profile_uid'], 'system', 'use_browser_location')) ? t('Clear browser location') : ''), '$shortnoloc' => t('clear location'), '$title' => ((x($x, 'title')) ? htmlspecialchars($x['title'], ENT_COMPAT,'UTF-8') : ''), - '$placeholdertitle' => t('Title (optional)'), + '$placeholdertitle' => ((x($x, 'placeholdertitle')) ? $x['placeholdertitle'] : t('Title (optional)')), + '$hidetitle' => ((x($x, 'hidetitle')) ? $x['hidetitle'] : false), '$catsenabled' => ((feature_enabled($x['profile_uid'], 'categories') && (! $webpage)) ? 'categories' : ''), '$category' => "", '$placeholdercategory' => t('Categories (optional, comma-separated list)'), @@ -1208,6 +1211,7 @@ function status_editor($a, $x, $popup = false) { '$shortpermset' => t('permissions'), '$ptyp' => (($notes_cid) ? 'note' : 'wall'), '$content' => ((x($x,'body')) ? htmlspecialchars($x['body'], ENT_COMPAT,'UTF-8') : ''), + '$attachment' => ((x($x, 'attachment')) ? $x['attachment'] : ''), '$post_id' => '', '$baseurl' => $a->get_baseurl(true), '$defloc' => $x['default_location'], @@ -1232,7 +1236,8 @@ function status_editor($a, $x, $popup = false) { '$encrypt' => t('Encrypt text'), '$cipher' => $cipher, '$expiryModalOK' => t('OK'), - '$expiryModalCANCEL' => t('Cancel') + '$expiryModalCANCEL' => t('Cancel'), + '$expanded' => ((x($x, 'expanded')) ? $x['expanded'] : false), )); if ($popup === true) { @@ -1635,7 +1640,7 @@ function profile_tabs($a, $is_owner = false, $nickname = null){ ); } - if ($is_owner && feature_enabled($uid,'webpages')) { + if ($p['write_pages'] && feature_enabled($uid,'webpages')) { $tabs[] = array( 'label' => t('Webpages'), 'url' => $a->get_baseurl() . '/webpages/' . $nickname, diff --git a/include/dir_fns.php b/include/dir_fns.php index d1e26b637..ebaa7c427 100644 --- a/include/dir_fns.php +++ b/include/dir_fns.php @@ -116,7 +116,13 @@ function dir_sort_links() { // Build urls without order and pubforums so it's easy to tack on the changed value // Probably there's an easier way to do this - $current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : 'date'); + + $directory_sort_order = get_config('system','directory_sort_order'); + if(! $directory_sort_order) + $directory_sort_order = 'date'; + + + $current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order); $url = 'directory?f='; $tmp = array_merge($_GET,$_POST); diff --git a/include/event.php b/include/event.php index 05f01535c..5926b50f7 100644 --- a/include/event.php +++ b/include/event.php @@ -424,7 +424,7 @@ function event_store_item($arr, $event) { $private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0); - q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', item_flags = %d, item_private = %d WHERE id = %d AND uid = %d", + q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', item_flags = %d, item_private = %d, obj_type = '%s' WHERE id = %d AND uid = %d", dbesc($arr['summary']), dbesc($prefix . format_event_bbcode($arr)), dbesc($object), @@ -435,6 +435,7 @@ function event_store_item($arr, $event) { dbesc($arr['edited']), intval($r[0]['item_flags']), intval($private), + dbesc(ACTIVITY_OBJ_EVENT), intval($r[0]['id']), intval($arr['uid']) ); diff --git a/include/items.php b/include/items.php index 4b83ce3e3..4e85bef37 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 @@ -433,7 +436,7 @@ function post_activity_item($arr) { $arr['verb'] = ((x($arr,'verb')) ? $arr['verb'] : ACTIVITY_POST); $arr['obj_type'] = ((x($arr,'obj_type')) ? $arr['obj_type'] : ACTIVITY_OBJ_NOTE); - if($is_comment) + if(($is_comment) && ($arr['obj_type'] === ACTIVITY_OBJ_NOTE)) $arr['obj_type'] = ACTIVITY_OBJ_COMMENT; $arr['allow_cid'] = ((x($arr,'allow_cid')) ? $arr['allow_cid'] : $channel['channel_allow_cid']); @@ -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 @@ -3994,6 +4066,11 @@ function drop_item($id,$interactive = true,$stage = DROPITEM_NORMAL,$force = fal if(local_channel() && local_channel() == $item['uid']) $ok_to_delete = true; + // sys owned item, requires site admin to delete + $sys = get_sys_channel(); + if(is_site_admin() && $sys['channel_id'] == $item['uid']) + $ok_to_delete = true; + // author deletion $observer = $a->get_observer(); if($observer && $observer['xchan_hash'] && ($observer['xchan_hash'] === $item['author_xchan'])) @@ -4001,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", @@ -4029,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); @@ -4088,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()), @@ -4108,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']), @@ -4162,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 @@ -4181,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) @@ -4216,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) @@ -4243,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)) { @@ -4331,7 +4408,7 @@ function zot_feed($uid,$observer_xchan,$arr) { $limit = " LIMIT 100 "; if($mindate != NULL_DATE) { - $sql_extra .= " and ( created > '$mindate' or edited > '$mindate' ) "; + $sql_extra .= " and ( created > '$mindate' or changed > '$mindate' ) "; } if($message_id) { @@ -4343,25 +4420,25 @@ 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(); } if(is_sys_channel($uid)) { require_once('include/security.php'); - $r = q("SELECT parent, created from item + $r = q("SELECT parent, created, postopts 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) ); } else { - $r = q("SELECT parent, created from item + $r = q("SELECT parent, created, postopts 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) @@ -4369,10 +4446,16 @@ function zot_feed($uid,$observer_xchan,$arr) { } if($r) { + for($x = 0; $x < count($r); $x ++) { + if(strpos($r[$x]['postopts'],'nodeliver') !== false) { + unset($r[$x]); + } + } + $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) @@ -4453,7 +4536,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; } @@ -4491,12 +4574,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'])) { @@ -4537,6 +4620,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 ) "; } @@ -4559,12 +4643,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'); @@ -4593,7 +4677,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 @@ -4624,7 +4708,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); @@ -4668,9 +4752,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. @@ -4735,7 +4819,7 @@ function item_remove_cid($xchan_hash,$mid,$uid) { } // Set item permissions based on results obtained from linkify_tags() -function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, $profile_uid, $parent_item = false) { +function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, $profile_uid, $parent_item = false, &$private) { $first_access_tag = true; foreach($linkified as $x) { @@ -4745,9 +4829,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 = ''; @@ -4757,10 +4841,12 @@ function set_linkified_perms($linkified, &$str_contact_allow, &$str_group_allow, if(strpos($access_tag,'cid:') === 0) { $str_contact_allow .= '<' . substr($access_tag,4) . '>'; $access_tag = ''; + $private = 1; } elseif(strpos($access_tag,'gid:') === 0) { $str_group_allow .= '<' . substr($access_tag,4) . '>'; $access_tag = ''; + $private = 1; } } } @@ -4770,7 +4856,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/js_strings.php b/include/js_strings.php index 84c1d70fb..cae8da5de 100644 --- a/include/js_strings.php +++ b/include/js_strings.php @@ -21,6 +21,7 @@ function js_strings() { '$rating_text' => t('Describe (optional)'), '$submit' => t('Submit'), '$linkurl' => t('Please enter a link URL'), + '$leavethispage' => t('Unsaved changes. Are you sure you wish to leave this page?'), '$t01' => ((t('timeago.prefixAgo') != 'timeago.prefixAgo') ? t('timeago.prefixAgo') : ''), '$t02' => ((t('timeago.prefixFromNow') != 'timeago.prefixFromNow') ? t('timeago.prefixFromNow') : ''), diff --git a/include/menu.php b/include/menu.php index 81e986132..b4f4555a5 100644 --- a/include/menu.php +++ b/include/menu.php @@ -25,6 +25,7 @@ function menu_fetch($name,$uid,$observer_xchan) { } function menu_render($menu, $class='', $edit = false) { + if(! $menu) return ''; @@ -40,6 +41,7 @@ function menu_render($menu, $class='', $edit = false) { '$menu' => $menu['menu'], '$class' => $class, '$edit' => (($edit) ? t("Edit") : ''), + '$id' => $menu['menu']['menu_id'], '$items' => $menu['items'] )); } @@ -60,14 +62,13 @@ function menu_fetch_id($menu_id,$channel_id) { function menu_create($arr) { - $menu_name = trim(escape_tags($arr['menu_name'])); $menu_desc = trim(escape_tags($arr['menu_desc'])); $menu_flags = intval($arr['menu_flags']); - - if(! $menu_desc) - $menu_desc = $menu_name; + //allow menu_desc (title) to be empty + //if(! $menu_desc) + // $menu_desc = $menu_name; if(! $menu_name) return false; @@ -144,8 +145,9 @@ function menu_edit($arr) { $menu_desc = trim(escape_tags($arr['menu_desc'])); $menu_flags = intval($arr['menu_flags']); - if(! $menu_desc) - $menu_desc = $menu_name; + //allow menu_desc (title) to be empty + //if(! $menu_desc) + // $menu_desc = $menu_name; if(! $menu_name) return false; @@ -227,31 +229,10 @@ function menu_add_item($menu_id, $uid, $arr) { $channel = get_app()->get_channel(); } - if (($channel) - && (! $arr['contact_allow']) - && (! $arr['group_allow']) - && (! $arr['contact_deny']) - && (! $arr['group_deny'])) { - $str_group_allow = $channel['channel_allow_gid']; - $str_contact_allow = $channel['channel_allow_cid']; - $str_group_deny = $channel['channel_deny_gid']; - $str_contact_deny = $channel['channel_deny_cid']; - } - else { - - // use the posted permissions - - $str_group_allow = perms2str($arr['group_allow']); - $str_contact_allow = perms2str($arr['contact_allow']); - $str_group_deny = perms2str($arr['group_deny']); - $str_contact_deny = perms2str($arr['contact_deny']); - } - -// unused -// $allow_cid = perms2str($arr['allow_cid']); -// $allow_gid = perms2str($arr['allow_gid']); -// $deny_cid = perms2str($arr['deny_cid']); -// $deny_gid = perms2str($arr['deny_gid']); + $str_group_allow = perms2str($arr['group_allow']); + $str_contact_allow = perms2str($arr['contact_allow']); + $str_group_deny = perms2str($arr['group_deny']); + $str_contact_deny = perms2str($arr['contact_deny']); $r = q("insert into menu_item ( mitem_link, mitem_desc, mitem_flags, allow_cid, allow_gid, deny_cid, deny_gid, mitem_channel_id, mitem_menu_id, mitem_order ) values ( '%s', '%s', %d, '%s', '%s', '%s', '%s', %d, %d, %d ) ", dbesc($mitem_link), @@ -283,25 +264,10 @@ function menu_edit_item($menu_id, $uid, $arr) { $channel = get_app()->get_channel(); } - if ((! $arr['contact_allow']) - && (! $arr['group_allow']) - && (! $arr['contact_deny']) - && (! $arr['group_deny'])) { - $str_group_allow = $channel['channel_allow_gid']; - $str_contact_allow = $channel['channel_allow_cid']; - $str_group_deny = $channel['channel_deny_gid']; - $str_contact_deny = $channel['channel_deny_cid']; - } - else { - - // use the posted permissions - - $str_group_allow = perms2str($arr['group_allow']); - $str_contact_allow = perms2str($arr['contact_allow']); - $str_group_deny = perms2str($arr['group_deny']); - $str_contact_deny = perms2str($arr['contact_deny']); - } - + $str_group_allow = perms2str($arr['group_allow']); + $str_contact_allow = perms2str($arr['contact_allow']); + $str_group_deny = perms2str($arr['group_deny']); + $str_contact_deny = perms2str($arr['contact_deny']); $r = q("update menu_item set mitem_link = '%s', mitem_desc = '%s', mitem_flags = %d, allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', mitem_order = %d where mitem_channel_id = %d and mitem_menu_id = %d and mitem_id = %d", dbesc($mitem_link), diff --git a/include/notifier.php b/include/notifier.php index bec18142a..b82fb41cc 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -343,6 +343,11 @@ function notifier_run($argv, $argc){ $deleted_item = true; } + if(strpos($target_item['postopts'],'nodeliver') !== false) { + logger('notifier: target item is undeliverable', LOGGER_DEBUG); + return; + } + $unforwardable = ITEM_UNPUBLISHED|ITEM_DELAYED_PUBLISH|ITEM_WEBPAGE|ITEM_BUILDBLOCK|ITEM_PDL; if($target_item['item_restrict'] & $unforwardable) { logger('notifier: target item not forwardable: flags ' . $target_item['item_restrict'], LOGGER_DEBUG); @@ -373,6 +378,12 @@ function notifier_run($argv, $argc){ if(! $r) return; + + if(strpos($r[0]['postopts'],'nodeliver') !== false) { + logger('notifier: target item is undeliverable', LOGGER_DEBUG); + return; + } + xchan_query($r); $r = fetch_post_tags($r); @@ -591,16 +602,13 @@ function notifier_run($argv, $argc){ foreach($dhubs as $hub) { - if(defined('DIASPORA_RELIABILITY_EMULATION')) { - $cointoss = mt_rand(0,2); - if($cointoss == 2) { + if($hub['hubloc_network'] === 'diaspora' || $hub['hubloc_network'] === 'friendica-over-diaspora') { + if(! get_config('system','diaspora_enabled')) continue; - } - } + // allow this to be set per message - if($hub['hubloc_network'] === 'diaspora' || $hub['hubloc_network'] === 'friendica-over-diaspora') { - if(! get_config('system','diaspora_enabled')) + if(strpos($target_item['postopts'],'nodspr') !== false) continue; require_once('include/diaspora.php'); diff --git a/include/permissions.php b/include/permissions.php index 82145066b..68ff2b3d4 100644 --- a/include/permissions.php +++ b/include/permissions.php @@ -422,12 +422,12 @@ function site_default_perms() { 'post_wall' => PERMS_SPECIFIC, 'post_comments' => PERMS_SPECIFIC, 'post_mail' => PERMS_SPECIFIC, - 'post_photos' => 0, + 'post_photos' => PERMS_SPECIFIC, 'tag_deliver' => PERMS_SPECIFIC, 'chat' => PERMS_SPECIFIC, - 'write_storage' => 0, - 'write_pages' => 0, - 'delegate' => 0, + 'write_storage' => PERMS_SPECIFIC, + 'write_pages' => PERMS_SPECIFIC, + 'delegate' => PERMS_SPECIFIC, 'post_like' => PERMS_NETWORK ); @@ -487,13 +487,13 @@ function get_role_perms($role) { $ret['channel_w_tagwall'] = PERMS_SPECIFIC; $ret['channel_w_comment'] = PERMS_SPECIFIC; $ret['channel_w_mail'] = PERMS_SPECIFIC; - $ret['channel_w_photos'] = 0; + $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_SPECIFIC; $ret['channel_w_like'] = PERMS_NETWORK; @@ -519,13 +519,13 @@ function get_role_perms($role) { $ret['channel_w_tagwall'] = PERMS_SPECIFIC; $ret['channel_w_comment'] = PERMS_SPECIFIC; $ret['channel_w_mail'] = PERMS_SPECIFIC; - $ret['channel_w_photos'] = 0; + $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_SPECIFIC; $ret['channel_w_like'] = PERMS_SPECIFIC; @@ -551,13 +551,13 @@ function get_role_perms($role) { $ret['channel_w_tagwall'] = PERMS_SPECIFIC; $ret['channel_w_comment'] = PERMS_SPECIFIC; $ret['channel_w_mail'] = PERMS_SPECIFIC; - $ret['channel_w_photos'] = 0; + $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_SPECIFIC; $ret['channel_w_like'] = PERMS_SPECIFIC; @@ -679,13 +679,13 @@ function get_role_perms($role) { $ret['channel_w_tagwall'] = PERMS_SPECIFIC; $ret['channel_w_comment'] = PERMS_SPECIFIC; $ret['channel_w_mail'] = PERMS_SPECIFIC; - $ret['channel_w_photos'] = 0; + $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_NETWORK; $ret['channel_w_like'] = PERMS_NETWORK; @@ -711,13 +711,13 @@ function get_role_perms($role) { $ret['channel_w_tagwall'] = PERMS_SPECIFIC; $ret['channel_w_comment'] = PERMS_SPECIFIC; $ret['channel_w_mail'] = PERMS_SPECIFIC; - $ret['channel_w_photos'] = 0; + $ret['channel_w_photos'] = PERMS_SPECIFIC; $ret['channel_w_chat'] = PERMS_SPECIFIC; - $ret['channel_a_delegate'] = 0; + $ret['channel_a_delegate'] = PERMS_SPECIFIC; $ret['channel_r_storage'] = PERMS_PUBLIC; - $ret['channel_w_storage'] = 0; + $ret['channel_w_storage'] = PERMS_SPECIFIC; $ret['channel_r_pages'] = PERMS_PUBLIC; - $ret['channel_w_pages'] = 0; + $ret['channel_w_pages'] = PERMS_SPECIFIC; $ret['channel_a_republish'] = PERMS_SPECIFIC; $ret['channel_w_like'] = PERMS_NETWORK; diff --git a/include/socgraph.php b/include/socgraph.php index 7f03f8696..0ad7c4034 100644 --- a/include/socgraph.php +++ b/include/socgraph.php @@ -180,6 +180,26 @@ function poco_load($xchan = '', $url = null) { } $total ++; + + + $r = q("select * from xlink where xlink_xchan = '%s' and xlink_link = '%s' and xlink_static = 0 limit 1", + dbesc($xchan), + dbesc($hash) + ); + + if(! $r) { + q("insert into xlink ( xlink_xchan, xlink_link, xlink_updated, xlink_static ) values ( '%s', '%s', '%s', 0 ) ", + dbesc($xchan), + dbesc($hash), + dbesc(datetime_convert()) + ); + } + else { + q("update xlink set xlink_updated = '%s' where xlink_id = %d", + dbesc(datetime_convert()), + intval($r[0]['xlink_id']) + ); + } } logger("poco_load: loaded $total entries",LOGGER_DEBUG); @@ -450,7 +470,7 @@ function poco($a,$extended = false) { $sql_extra = " and abook_flags = 0 "; if($cid) - $sql_extra = sprintf(" and abook_id = %d ",intval($cid)); + $sql_extra = sprintf(" and abook_id = %d and ( abook_flags & " . ABOOK_FLAG_HIDDEN . " ) = 0 ",intval($cid)); if($system_mode) { $r = q("SELECT count(*) as `total` from abook where ( abook_flags & " . ABOOK_FLAG_SELF . diff --git a/include/taxonomy.php b/include/taxonomy.php index 4333cdf03..fa540ac56 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -275,6 +275,11 @@ function catblock($uid,$count = 0,$authors = '',$flags = 0,$restrict = 0,$type = function dir_tagblock($link,$r) { $o = ''; + $observer = get_observer_hash(); + if(! get_globaldir_setting($observer)) + return $o; + + if(! $r) $r = get_app()->data['directory_keywords']; diff --git a/include/text.php b/include/text.php index 664d5f83d..deb5a4c90 100644 --- a/include/text.php +++ b/include/text.php @@ -98,12 +98,20 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') { return escape_tags($s); if($type == 'text/plain') return escape_tags($s); + + $a = get_app(); + if($a->is_sys) { + return $s; + } + $r = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id where channel_id = %d limit 1", intval($channel_id) ); - if($r && (($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($r[0]['channel_pageflags'] & PAGE_ALLOWCODE))) { - if(local_channel() && (get_account_id() == $r[0]['account_id'])) { - return $s; + if($r) { + if(($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($r[0]['channel_pageflags'] & PAGE_ALLOWCODE)) { + if(local_channel() && (get_account_id() == $r[0]['account_id'])) { + return $s; + } } } @@ -1034,9 +1042,9 @@ function list_smilies() { '<img class="smiley" src="' . $a->get_baseurl() . '/images/smiley-facepalm.gif" alt=":facepalm" />', '<img class="smiley" src="' . $a->get_baseurl() . '/images/like.gif" alt=":like" />', '<img class="smiley" src="' . $a->get_baseurl() . '/images/dislike.gif" alt=":dislike" />', - '<a href="http://getzot.com"><strong>red<img class="smiley" src="' . $a->get_baseurl() . '/images/rm-16.png" alt="' . urlencode('red#matrix') . '" />matrix</strong></a>', - '<a href="http://getzot.com"><strong>red<img class="smiley" src="' . $a->get_baseurl() . '/images/rm-16.png" alt="' . urlencode('red#') . '" />matrix</strong></a>', - '<a href="http://getzot.com"><strong>red<img class="smiley" src="' . $a->get_baseurl() . '/images/rm-16.png" alt="r#" />matrix</strong></a>' + '<a href="http://getzot.com"><strong>red<img class="smiley bb_rm-logo" src="' . $a->get_baseurl() . '/images/rm-32.png" alt="' . urlencode('red#matrix') . '" />matrix</strong></a>', + '<a href="http://getzot.com"><strong>red<img class="smiley bb_rm-logo" src="' . $a->get_baseurl() . '/images/rm-32.png" alt="' . urlencode('red#') . '" />matrix</strong></a>', + '<a href="http://getzot.com"><strong>red<img class="smiley bb_rm-logo" src="' . $a->get_baseurl() . '/images/rm-32.png" alt="r#" />matrix</strong></a>' ); @@ -1177,9 +1185,28 @@ function unobscure(&$item) { $item['title'] = crypto_unencapsulate(json_decode_plus($item['title']),$key); if($item['body']) $item['body'] = crypto_unencapsulate(json_decode_plus($item['body']),$key); + if(get_config('system','item_cache')) { + q("update item set title = '%s', body = '%s', item_flags = %d where id = %d", + dbesc($item['title']), + dbesc($item['body']), + intval($item['item_flags'] - ITEM_OBSCURED), + intval($item['id']) + ); + } } } +function unobscure_mail(&$item) { + if(array_key_exists('mail_flags',$item) && ($item['mail_flags'] & MAIL_OBSCURED)) { + $key = get_config('system','prvkey'); + if($item['title']) + $item['title'] = crypto_unencapsulate(json_decode_plus($item['title']),$key); + if($item['body']) + $item['body'] = crypto_unencapsulate(json_decode_plus($item['body']),$key); + } +} + + function theme_attachments(&$item) { $arr = json_decode_plus($item['attach']); @@ -1258,15 +1285,19 @@ function format_categories(&$item,$writeable) { return $s; } -// Add any hashtags which weren't mentioned in the message body, e.g. community tags - +/** + * @brief Add any hashtags which weren't mentioned in the message body, e.g. community tags + * + * @param[in] array &$item + * @return string HTML link of hashtag + */ function format_hashtags(&$item) { - $s = ''; - $terms = get_terms_oftype($item['term'],TERM_HASHTAG); + + $terms = get_terms_oftype($item['term'], TERM_HASHTAG); if($terms) { foreach($terms as $t) { - $term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ; + $term = htmlspecialchars($t['term'], ENT_COMPAT, 'UTF-8', false) ; if(! trim($term)) continue; if(strpos($item['body'], $t['url'])) @@ -1278,6 +1309,7 @@ function format_hashtags(&$item) { $s .= '#<a href="' . zid($t['url']) . '" >' . $term . '</a>'; } } + return $s; } @@ -1301,6 +1333,7 @@ function format_mentions(&$item) { $s .= '@<a href="' . zid($t['url']) . '" >' . $term . '</a>'; } } + return $s; } @@ -1346,8 +1379,12 @@ function generate_named_map($location) { function prepare_body(&$item,$attach = false) { + if(get_config('system','item_cache') && $item['html']) + return $item['html']; + call_hooks('prepare_body_init', $item); + unobscure($item); $s = prepare_text($item['body'],$item['mimetype']); @@ -1415,6 +1452,12 @@ function prepare_body(&$item,$attach = false) { $prep_arr = array('item' => $item, 'html' => $s); call_hooks('prepare_body_final', $prep_arr); + if(get_config('system','item_cache')) + q("update item set html = '%s' where id = %d", + dbesc($prep_arr['html']), + intval($item['id']) + ); + return $prep_arr['html']; } @@ -1581,18 +1624,20 @@ function layout_select($channel_id, $current = '') { intval($channel_id), intval(ITEM_PDL) ); + if($r) { - $o = t('Select a page layout: '); - $o .= '<select name="layout_mid" id="select-layout_mid" >'; - $empty_selected = (($current === '') ? ' selected="selected" ' : ''); - $o .= '<option value="" ' . $empty_selected . '>' . t('default') . '</option>'; + $empty_selected = (($current === false) ? ' selected="selected" ' : ''); + $options .= '<option value="" ' . $empty_selected . '>' . t('default') . '</option>'; foreach($r as $rr) { $selected = (($rr['mid'] == $current) ? ' selected="selected" ' : ''); - $o .= '<option value="' . $rr['mid'] . '"' . $selected . '>' . $rr['sid'] . '</option>'; + $options .= '<option value="' . $rr['mid'] . '"' . $selected . '>' . $rr['sid'] . '</option>'; } - $o .= '</select>'; } + $o = replace_macros(get_markup_template('field_select_raw.tpl'), array( + '$field' => array('layout_mid', t('Page layout'), $selected, t('You can create your own with the layouts tool'), $options) + )); + return $o; } @@ -1606,25 +1651,33 @@ function mimetype_select($channel_id, $current = 'text/bbcode') { 'text/plain' ); - $r = q("select account_id, account_roles, channel_pageflags from account left join channel on account_id = channel_account_id where - channel_id = %d limit 1", - intval($channel_id) - ); + $a = get_app(); + if($a->is_sys) { + $x[] = 'application/x-php'; + } + else { + $r = q("select account_id, account_roles, channel_pageflags from account left join channel on account_id = channel_account_id where + channel_id = %d limit 1", + intval($channel_id) + ); - if($r) { - if(($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($r[0]['channel_pageflags'] & PAGE_ALLOWCODE)) { - if(local_channel() && get_account_id() == $r[0]['account_id']) - $x[] = 'application/x-php'; - } + if($r) { + if(($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($r[0]['channel_pageflags'] & PAGE_ALLOWCODE)) { + if(local_channel() && get_account_id() == $r[0]['account_id']) { + $x[] = 'application/x-php'; + } + } + } } - $o = t('Page content type: '); - $o .= '<select name="mimetype" id="mimetype-select">'; foreach($x as $y) { - $select = (($y == $current) ? ' selected="selected" ' : ''); - $o .= '<option name="' . $y . '"' . $select . '>' . $y . '</option>'; + $selected = (($y == $current) ? ' selected="selected" ' : ''); + $options .= '<option name="' . $y . '"' . $selected . '>' . $y . '</option>'; } - $o .= '</select>'; + + $o = replace_macros(get_markup_template('field_select_raw.tpl'), array( + '$field' => array('mimetype', t('Page content type'), $selected, '', $options) + )); return $o; } @@ -2065,7 +2118,11 @@ function json_decode_plus($s) { return $x; } - +/** + * @brief Creates navigation menu for webpage, layout, blocks, menu sites. + * + * @return string + */ function design_tools() { $channel = get_app()->get_channel(); @@ -2080,7 +2137,7 @@ function design_tools() { $who = $channel['channel_address']; return replace_macros(get_markup_template('design_tools.tpl'), array( - '$title' => t('Design'), + '$title' => t('Design Tools'), '$who' => $who, '$sys' => $sys, '$blocks' => t('Blocks'), diff --git a/include/widgets.php b/include/widgets.php index 243c4a25e..4a9032a21 100644 --- a/include/widgets.php +++ b/include/widgets.php @@ -420,18 +420,35 @@ function widget_affinity($arr) { $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : 0); $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : 99); + if(feature_enabled(local_channel(),'affinity')) { + + $labels = array( + t('Me'), + t('Family'), + t('Friends'), + t('Acquaintances'), + t('All') + ); + call_hooks('affinity_labels',$labels); + $label_str = ''; + + if($labels) { + foreach($labels as $l) { + if($label_str) { + $label_str .= ", '|'"; + $label_str .= ", '" . $l . "'"; + } + else + $label_str .= "'" . $l . "'"; + } + } + $tpl = get_markup_template('main_slider.tpl'); $x = replace_macros($tpl,array( '$val' => $cmin . ',' . $cmax, '$refresh' => t('Refresh'), - '$me' => t('Me'), - '$intimate' => t('Best Friends'), - '$friends' => t('Friends'), - '$coworkers' => t('Co-workers'), - '$oldfriends' => t('Former Friends'), - '$acquaintances' => t('Acquaintances'), - '$world' => t('Everybody') + '$labels' => $label_str, )); $arr = array('html' => $x); call_hooks('main_slider',$arr); @@ -968,4 +985,4 @@ function widget_pubsites() { if(get_app()->poi) return; return '<div class="widget"><ul class="nav nav-pills"><li><a href="pubsites">' . t('Public Hubs') . '</a></li></ul></div>'; -}
\ No newline at end of file +} 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']), |