From 6c92b5ab86d7f0fee775c2c485f5264ac2b206be Mon Sep 17 00:00:00 2001 From: friendica Date: Thu, 20 Sep 2012 17:04:22 -0700 Subject: separate the public feed from everything else --- include/Contact.php | 5 ++ include/conversation.php | 88 +++++++++++++++++++++--------- include/items.php | 137 ++++++++++++++++++++++++++++++++++++++++------- mod/events.php | 18 ++++++- mod/feed.php | 39 ++++++++++++++ mod/parse_url.php | 26 ++++++--- version.inc | 2 +- 7 files changed, 261 insertions(+), 54 deletions(-) create mode 100644 mod/feed.php diff --git a/include/Contact.php b/include/Contact.php index 571c956f1..d4d29b297 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -8,6 +8,11 @@ function map_perms($entity,$zguid,$zsig) { $is_network = false; $is_anybody = true; + + // To avoid sending the lengthy target_sig with each request, + // We should provide an array of results for each target + // and let the sender match the signature. + if(strlen($zguid) && strlen($zsig)) { $is_network = true; diff --git a/include/conversation.php b/include/conversation.php index b5faa0b34..621032349 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -89,7 +89,7 @@ function localize_item(&$item){ $item['body'] = item_redir_and_replace_images($extracted['body'], $extracted['images'], $item['contact-id']); $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">"; - if ($item['verb']=== ACTIVITY_LIKE || $item['verb']=== ACTIVITY_DISLIKE){ + if (activity_match($item['verb'],ACTIVITY_LIKE) || activity_match($item['verb'],ACTIVITY_DISLIKE)){ $r = q("SELECT * from `item`,`contact` WHERE `item`.`contact-id`=`contact`.`id` AND `item`.`uri`='%s';", @@ -122,18 +122,16 @@ function localize_item(&$item){ $plink = '[url=' . $obj['plink'] . ']' . $post_type . '[/url]'; - switch($item['verb']){ - case ACTIVITY_LIKE : - $bodyverb = t('%1$s likes %2$s\'s %3$s'); - break; - case ACTIVITY_DISLIKE: - $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s'); - break; + if(activity_match($item['verb'],ACTIVITY_LIKE)) { + $bodyverb = t('%1$s likes %2$s\'s %3$s'); + } + elseif(activity_match($item['verb'],ACTIVITY_DISLIKE)) { + $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s'); } $item['body'] = sprintf($bodyverb, $author, $objauthor, $plink); } - if ($item['verb']=== ACTIVITY_FRIEND){ + if (activity_match($item['verb'],ACTIVITY_FRIEND)) { if ($item['obj_type']=="" || $item['obj_type']!== ACTIVITY_OBJ_PERSON) return; @@ -220,7 +218,7 @@ function localize_item(&$item){ $item['body'] = sprintf($txt, $A, t($verb)); } - if ($item['verb']===ACTIVITY_TAG){ + if (activity_match($item['verb'],ACTIVITY_TAG)) { $r = q("SELECT * from `item`,`contact` WHERE `item`.`contact-id`=`contact`.`id` AND `item`.`uri`='%s';", dbesc($item['parent_uri'])); @@ -257,7 +255,7 @@ function localize_item(&$item){ $item['body'] = sprintf( t('%1$s tagged %2$s\'s %3$s with %4$s'), $author, $objauthor, $plink, $tag ); } - if ($item['verb']=== ACTIVITY_FAVORITE){ + if (activity_match($item['verb'],ACTIVITY_FAVORITE)){ if ($item['obj_type']== "") return; @@ -315,20 +313,31 @@ function localize_item(&$item){ * Count the total of comments on this item and its desendants */ function count_descendants($item) { + $total = count($item['children']); - if($item['verb'] === ACTIVITY_LIKE || $item['verb'] === ACTIVITY_DISLIKE) - return 0; - - if($total > 0) { - foreach($item['children'] as $child) { - $total += count_descendants($child); - } - } + if($total > 0) { + foreach($item['children'] as $child) { + if(! visible_activity($child)) + $total --; + $total += count_descendants($child); + } + } return $total; } +function visible_activity($item) { + + if(activity_match($child['verb'],ACTIVITY_LIKE) || activity_match($child['verb'],ACTIVITY_DISLIKE)) + return false; + + if(activity_match($item['verb'],ACTIVITY_FOLLOW) && $item['object-type'] === ACTIVITY_OBJ_NOTE && $item['uid'] != local_user()) + return false; + + return true; +} + /** * Recursively prepare a thread for HTML */ @@ -345,8 +354,9 @@ function prepare_threads_body($a, $items, $cmnt_tpl, $page_writeable, $mode, $pr foreach($items as $item) { - if($item['verb'] === ACTIVITY_LIKE || $item['verb'] === ACTIVITY_DISLIKE) { + if(! visible_activity($item)) { $nb_items --; + $total_children --; continue; } @@ -433,9 +443,19 @@ function prepare_threads_body($a, $items, $cmnt_tpl, $page_writeable, $mode, $pr $location = ((strlen($locate['html'])) ? $locate['html'] : render_location_google($locate)); $tags=array(); + $hashtags = array(); + $mentions = array(); foreach(explode(',',$item['tag']) as $tag){ $tag = trim($tag); - if ($tag!="") $tags[] = bbcode($tag); + if ($tag!="") { + $t = bbcode($tag); + $tags[] = $t; + if($t[0] == '#') + $hashtags[] = $t; + elseif($t[0] == '@') + $mentions[] = $t; + } + } $like = ((x($alike,$item['uri'])) ? format_like($alike[$item['uri']],$alike[$item['uri'] . '-l'],'like',$item['uri']) : ''); @@ -586,7 +606,9 @@ function prepare_threads_body($a, $items, $cmnt_tpl, $page_writeable, $mode, $pr 'template' => $template, 'type' => implode("",array_slice(explode("/",$item['verb']),-1)), - 'tags' => $tags, + 'tags' => template_escape($tags), + 'hashtags' => template_escape($hashtags), + 'mentions' => template_escape($mentions), 'body' => template_escape($body), 'text' => strip_tags(template_escape($body)), 'id' => $item['item_id'], @@ -777,6 +799,21 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') { + $tags=array(); + $hashtags = array(); + $mentions = array(); + foreach(explode(',',$item['tag']) as $tag){ + $tag = trim($tag); + if ($tag!="") { + $t = bbcode($tag); + $tags[] = $t; + if($t[0] == '#') + $hashtags[] = $t; + elseif($t[0] == '@') + $mentions[] = $t; + } + } + $sp = false; $profile_link = best_link_url($item,$sp); if($sp) @@ -839,6 +876,9 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') { 'thumb' => $profile_avatar, 'title' => template_escape($item['title']), 'body' => template_escape($body), + 'tags' => template_escape($tags), + 'hashtags' => template_escape($hashtags), + 'mentions' => template_escape($mentions), 'text' => strip_tags(template_escape($body)), 'ago' => relative_date($item['created']), 'app' => $item['app'], @@ -928,9 +968,7 @@ function conversation(&$a, $items, $mode, $update, $page_mode = 'traditional') { // We've already parsed out like/dislike for special treatment. We can ignore them now - if(((activity_match($item['verb'],ACTIVITY_LIKE)) - || (activity_match($item['verb'],ACTIVITY_DISLIKE))) - && ($item['id'] != $item['parent'])) + if((! visible_activity($item)) && ($item['id'] != $item['parent'])) continue; $toplevelpost = (($item['id'] == $item['parent']) ? true : false); diff --git a/include/items.php b/include/items.php index 4acf72d77..ba7d54c94 100755 --- a/include/items.php +++ b/include/items.php @@ -7,6 +7,40 @@ require_once('include/crypto.php'); require_once('include/Photo.php'); +function get_public_feed($channel,$params) { + + $type = 'xml'; + $begin = '0000-00-00 00:00:00'; + $end = ''; + $start = 0; + $records = 40; + $direction = 'desc'; + + if(is_array($params)) { + $type = ((x($params,'type')) ? $params['type'] : $type); + $begin = ((x($params,'begin')) ? $params['begin'] : $begin); + $end = ((x($params,'end')) ? $params['end'] : $end); + $start = ((x($params,'start')) ? $params['start'] : $start); + $records = ((x($params,'records')) ? $params['records'] : $records); + $direction = ((x($params,'direction')) ? $params['direction'] : $direction); + } + + switch($type) { + case 'json': + header("Content-type: application/atom+json"); + break; + case 'xml': + default: + header("Content-type: application/atom+xml"); + break; + } + + + + + +} + function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) { @@ -1231,6 +1265,15 @@ function tag_deliver($uid,$item_id) { // send a notification + // use a local photo if we have one + + $r = q("select thumb from contact where uid = %d and nurl = '%s' limit 1", + intval($u[0]['uid']), + dbesc(normalise_link($item['author-link'])) + ); + $photo = (($r && count($r)) ? $r[0]['thumb'] : $item['author-avatar']); + + require_once('include/enotify.php'); notification(array( 'type' => NOTIFY_TAGSELF, @@ -1243,7 +1286,7 @@ function tag_deliver($uid,$item_id) { 'link' => $a->get_baseurl() . '/display/' . $u[0]['nickname'] . '/' . $item['id'], 'source_name' => $item['author-name'], 'source_link' => $item['author-link'], - 'source_photo' => $item['author-avatar'], + 'source_photo' => $photo, 'verb' => ACTIVITY_TAG, 'otype' => 'item' )); @@ -1294,6 +1337,59 @@ function tag_deliver($uid,$item_id) { +function tgroup_check($uid,$item) { + + $a = get_app(); + + $mention = false; + + // check that the message originated elsewhere and is a top-level post + + if(($item['wall']) || ($item['origin']) || ($item['uri'] != $item['parent-uri'])) + return false; + + + $u = q("select * from user where uid = %d limit 1", + intval($uid) + ); + if(! count($u)) + return false; + + $community_page = (($u[0]['page-flags'] == PAGE_COMMUNITY) ? true : false); + $prvgroup = (($u[0]['page-flags'] == PAGE_PRVGROUP) ? true : false); + + + $link = normalise_link($a->get_baseurl() . '/profile/' . $u[0]['nickname']); + + // Diaspora uses their own hardwired link URL in @-tags + // instead of the one we supply with webfinger + + $dlink = normalise_link($a->get_baseurl() . '/u/' . $u[0]['nickname']); + + $cnt = preg_match_all('/[\@\!]\[url\=(.*?)\](.*?)\[\/url\]/ism',$item['body'],$matches,PREG_SET_ORDER); + if($cnt) { + foreach($matches as $mtch) { + if(link_compare($link,$mtch[1]) || link_compare($dlink,$mtch[1])) { + $mention = true; + logger('tgroup_check: mention found: ' . $mtch[2]); + } + } + } + + if(! $mention) + return false; + + if((! $community_page) && (! $prvgroup)) + return false; + + + + return true; + +} + + + @@ -1831,6 +1927,12 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if($pass == 1) continue; + // not allowed to post + + if($contact['rel'] == CONTACT_IS_FOLLOWER) + continue; + + // Have we seen it? If not, import it. $item_id = $item->get_id(); @@ -2041,6 +2143,14 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) $datarray['owner-avatar'] = $contact['thumb']; } + // We've allowed "followers" to reach this point so we can decide if they are + // posting an @-tag delivery, which followers are allowed to do for certain + // page types. Now that we've parsed the post, let's check if it is legit. Otherwise ignore it. + + if(($contact['rel'] == CONTACT_IS_FOLLOWER) && (! tgroup_check($importer['uid'],$datarray))) + continue; + + $r = item_store($datarray); continue; @@ -2631,15 +2741,6 @@ function local_delivery($importer,$data) { } - // TODO: make this next part work against both delivery threads of a community post - -// if((! link_compare($datarray['author-link'],$importer['url'])) && (! $community)) { -// logger('local_delivery: received relay claiming to be from ' . $importer['url'] . ' however comment author url is ' . $datarray['author-link'] ); - // they won't know what to do so don't report an error. Just quietly die. -// return 0; -// } - - // our user with $importer['importer_uid'] is the owner $own = q("select name,url,thumb from contact where uid = %d and self = 1 limit 1", intval($importer['importer_uid']) @@ -2709,15 +2810,6 @@ function local_delivery($importer,$data) { } } -// if($community) { -// $newtag = '@[url=' . $a->get_baseurl() . '/profile/' . $importer['nickname'] . ']' . $importer['username'] . '[/url]'; -// if(! stristr($datarray['tag'],$newtag)) { -// if(strlen($datarray['tag'])) -// $datarray['tag'] .= ','; -// $datarray['tag'] .= $newtag; -// } -// } - $posted_id = item_store($datarray); $parent = 0; @@ -2787,6 +2879,10 @@ function local_delivery($importer,$data) { $item_id = $item->get_id(); $datarray = get_atom_elements($feed,$item); + if($importer['rel'] == CONTACT_IS_FOLLOWER) + continue; + + $r = q("SELECT `uid`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid']) @@ -2992,6 +3088,9 @@ function local_delivery($importer,$data) { $datarray['owner-avatar'] = $importer['thumb']; } + if(($importer['rel'] == CONTACT_IS_FOLLOWER) && (! tgroup_check($importer['importer_uid'],$datarray))) + continue; + $posted_id = item_store($datarray); if(stristr($datarray['verb'],ACTIVITY_POKE)) { diff --git a/mod/events.php b/mod/events.php index bf02f8309..f950b5adc 100755 --- a/mod/events.php +++ b/mod/events.php @@ -141,6 +141,20 @@ function events_content(&$a) { return; } + if(($a->argc > 2) && ($a->argv[1] === 'ignore') && intval($a->argv[2])) { + $r = q("update event set ignore = 1 where id = %d and uid = %d limit 1", + intval($a->argv[2]), + intval(local_user()) + ); + } + + if(($a->argc > 2) && ($a->argv[1] === 'unignore') && intval($a->argv[2])) { + $r = q("update event set ignore = 0 where id = %d and uid = %d limit 1", + intval($a->argv[2]), + intval(local_user()) + ); + } + $htpl = get_markup_template('event_head.tpl'); $a->page['htmlhead'] .= replace_macros($htpl,array('$baseurl' => $a->get_baseurl())); @@ -154,6 +168,7 @@ function events_content(&$a) { $mode = 'view'; $y = 0; $m = 0; + $ignored = ((x($_REQUEST,'ignored')) ? intval($_REQUEST['ignored']) : 0); if($a->argc > 1) { if($a->argc > 2 && $a->argv[1] == 'event') { @@ -231,10 +246,11 @@ function events_content(&$a) { } else { $r = q("SELECT `event`.*, `item`.`id` AS `itemid`,`item`.`plink`, `item`.`author-name`, `item`.`author-avatar`, `item`.`author-link` FROM `event` LEFT JOIN `item` ON `item`.`event-id` = `event`.`id` - WHERE `event`.`uid` = %d + WHERE `event`.`uid` = %d and ignore = %d AND (( `adjust` = 0 AND `finish` >= '%s' AND `start` <= '%s' ) OR ( `adjust` = 1 AND `finish` >= '%s' AND `start` <= '%s' )) ", intval(local_user()), + intval($ignored), dbesc($start), dbesc($finish), dbesc($adjust_start), diff --git a/mod/feed.php b/mod/feed.php new file mode 100644 index 000000000..69d8fdb05 --- /dev/null +++ b/mod/feed.php @@ -0,0 +1,39 @@ + 1) { + $r = q("select * from entity where entity_address = '%s' limit 1", + dbesc(argv(1)) + ); + if(!($r && count($r))) + killme(); + + $channel = $r[0]; + + // check site and channel permissions + + if(!($channel['entity_r_stream'] & PERMS_PUBLIC)) + killme(); + + if((intval(get_config('system','block_public'))) && (! get_account_id())) + killme(); + + logger('mod_feed: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $channel['entity_address']); + echo get_public_feed($channel,$params); + killme(); + } + +} + + diff --git a/mod/parse_url.php b/mod/parse_url.php index 083a39b55..9adee8f65 100644 --- a/mod/parse_url.php +++ b/mod/parse_url.php @@ -307,16 +307,26 @@ function parse_url_content(&$a) { $image = ""; - if(sizeof($siteinfo["images"]) > 0){ - /* - Execute below code only if image is present in siteinfo - */ - foreach ($siteinfo["images"] as $imagedata) - if($textmode) - $image .= '[img='.$imagedata["width"].'x'.$imagedata["height"].']'.$imagedata["src"].'[/img]'; + if(sizeof($siteinfo["images"]) > 0){ + /* Execute below code only if image is present in siteinfo */ + + $total_images = 0; + $max_images = get_config('system','max_bookmark_images'); + if($max_images === false) + $max_images = 2; else - $image .= 'photo'; + $max_images = intval($max_images); + + foreach ($siteinfo["images"] as $imagedata) { + if($textmode) + $image .= '[img='.$imagedata["width"].'x'.$imagedata["height"].']'.$imagedata["src"].'[/img]' . "\n"; + else + $image .= 'photo
'; + $total_images ++; + if($max_images && $max_images >= $total_images) + break; } + } if(strlen($text)) { if($textmode) diff --git a/version.inc b/version.inc index a9a3cd318..8f6893a76 100644 --- a/version.inc +++ b/version.inc @@ -1 +1 @@ -2012-09-10.73 +2012-09-20.83 -- cgit v1.2.3