X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fitems.php;h=aea5a4de5e9affaf1676cd89204ac2fc93ceae85;hb=6e0dd29c1b8f5dbe36428c334244b21a0414d08a;hp=701a7ada7ec3579596d5ffa525d8d14831c6b4ee;hpb=3484d3bc5ffdac5b6f447abcd8ceef9b681aa311;p=friendica.git diff --git a/include/items.php b/include/items.php index 701a7ada7e..aea5a4de5e 100755 --- a/include/items.php +++ b/include/items.php @@ -76,6 +76,7 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) killme(); $contact = $r[0]; + require_once('include/security.php'); $groups = init_groups_visitor($contact['id']); if(count($groups)) { @@ -578,6 +579,7 @@ function get_atom_elements($feed,$item) { $res['body'] = escape_tags($res['body']); } + // this tag is obsolete but we keep it for really old sites $allow = $item->get_item_tags(NAMESPACE_DFRN,'comment-allow'); @@ -924,6 +926,8 @@ function item_store($arr,$force_parent = false) { $arr['origin'] = ((x($arr,'origin')) ? intval($arr['origin']) : 0 ); $arr['guid'] = ((x($arr,'guid')) ? notags(trim($arr['guid'])) : get_guid()); + + $arr['thr-parent'] = $arr['parent-uri']; if($arr['parent-uri'] === $arr['uri']) { $parent_id = 0; $parent_deleted = 0; @@ -949,7 +953,6 @@ function item_store($arr,$force_parent = false) { // and re-attach to the conversation parent. if($r[0]['uri'] != $r[0]['parent-uri']) { - $arr['thr-parent'] = $arr['parent-uri']; $arr['parent-uri'] = $r[0]['parent-uri']; $z = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `parent-uri` = '%s' AND `uid` = %d ORDER BY `id` ASC LIMIT 1", @@ -991,7 +994,6 @@ function item_store($arr,$force_parent = false) { if($force_parent) { logger('item_store: $force_parent=true, reply converted to top-level post.'); $parent_id = 0; - $arr['thr-parent'] = $arr['parent-uri']; $arr['parent-uri'] = $arr['uri']; $arr['gravity'] = 0; } @@ -1183,6 +1185,15 @@ function tag_deliver($uid,$item_id) { // send a notification + // use a local photo if we have one + + $r = q("select * 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, @@ -1195,11 +1206,16 @@ 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' )); + + $arr = array('item' => $item, 'user' => $u[0], 'contact' => $r[0]); + + call_hooks('tagged', $arr); + if((! $community_page) && (! $prvgroup)) return; @@ -1246,6 +1262,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; + +} + + + @@ -1802,6 +1871,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(); @@ -2076,6 +2151,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; @@ -2085,9 +2168,10 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } function local_delivery($importer,$data) { - $a = get_app(); + logger(__function__, LOGGER_TRACE); + if($importer['readonly']) { // We aren't receiving stuff from this person. But we will quietly ignore them // rather than a blatant "go away" message. @@ -2121,8 +2205,11 @@ function local_delivery($importer,$data) { $rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'owner'); - if(! $rawtags) - $rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author'); + +// Fallback should not be needed here. If it isn't DFRN it won't have DFRN updated tags +// if(! $rawtags) +// $rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author'); + if($rawtags) { $elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]; if($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) { @@ -2135,7 +2222,7 @@ function local_delivery($importer,$data) { } } - if((is_array($contact)) && ($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $importer['avatar-date'])) { + if(($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $importer['avatar-date'])) { logger('local_delivery: Updating photo for ' . $importer['name']); require_once("Photo.php"); $photo_failure = false; @@ -2193,7 +2280,7 @@ function local_delivery($importer,$data) { } } - if((is_array($contact)) && ($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) { + if(($name_updated) && (strlen($new_name)) && ($name_updated > $importer['name-date'])) { $r = q("select * from contact where uid = %d and id = %d limit 1", intval($importer['importer_uid']), intval($importer['id']) @@ -2219,7 +2306,7 @@ function local_delivery($importer,$data) { } -/* + // Currently unsupported - needs a lot of work $reloc = $feed->get_feed_tags( NAMESPACE_DFRN, 'relocate' ); if(isset($reloc[0]['child'][NAMESPACE_DFRN])) { @@ -2229,23 +2316,79 @@ function local_delivery($importer,$data) { $newloc['cid'] = $importer['id']; $newloc['name'] = notags(unxmlify($base['name'][0]['data'])); $newloc['photo'] = notags(unxmlify($base['photo'][0]['data'])); + $newloc['thumb'] = notags(unxmlify($base['thumb'][0]['data'])); + $newloc['micro'] = notags(unxmlify($base['micro'][0]['data'])); $newloc['url'] = notags(unxmlify($base['url'][0]['data'])); $newloc['request'] = notags(unxmlify($base['request'][0]['data'])); $newloc['confirm'] = notags(unxmlify($base['confirm'][0]['data'])); $newloc['notify'] = notags(unxmlify($base['notify'][0]['data'])); $newloc['poll'] = notags(unxmlify($base['poll'][0]['data'])); - $newloc['site-pubkey'] = notags(unxmlify($base['site-pubkey'][0]['data'])); - $newloc['pubkey'] = notags(unxmlify($base['pubkey'][0]['data'])); - $newloc['prvkey'] = notags(unxmlify($base['prvkey'][0]['data'])); + $newloc['sitepubkey'] = notags(unxmlify($base['sitepubkey'][0]['data'])); + /** relocated user must have original key pair */ + /*$newloc['pubkey'] = notags(unxmlify($base['pubkey'][0]['data'])); + $newloc['prvkey'] = notags(unxmlify($base['prvkey'][0]['data']));*/ + + logger("items:relocate contact ".print_r($newloc, true).print_r($importer, true), LOGGER_DEBUG); + + // update contact + $r = q("SELECT photo, url FROM contact WHERE id=%d AND uid=%d;", + intval($importer['id']), + intval($importer['importer_uid'])); + if ($r === false) + return 1; + $old = $r[0]; + + $x = q("UPDATE contact SET + name = '%s', + photo = '%s', + thumb = '%s', + micro = '%s', + url = '%s', + request = '%s', + confirm = '%s', + notify = '%s', + poll = '%s', + `site-pubkey` = '%s' + WHERE id=%d AND uid=%d;", + dbesc($newloc['name']), + dbesc($newloc['photo']), + dbesc($newloc['thumb']), + dbesc($newloc['micro']), + dbesc($newloc['url']), + dbesc($newloc['request']), + dbesc($newloc['confirm']), + dbesc($newloc['notify']), + dbesc($newloc['poll']), + dbesc($newloc['sitepubkey']), + intval($importer['id']), + intval($importer['importer_uid'])); + + if ($x === false) + return 1; + // update items + $fields = array( + 'owner-link' => array($old['url'], $newloc['url']), + 'author-link' => array($old['url'], $newloc['url']), + 'owner-avatar' => array($old['photo'], $newloc['photo']), + 'author-avatar' => array($old['photo'], $newloc['photo']), + ); + foreach ($fields as $n=>$f){ + $x = q("UPDATE item SET `%s`='%s' WHERE `%s`='%s' AND uid=%d", + $n, dbesc($f[1]), + $n, dbesc($f[0]), + intval($importer['importer_uid'])); + if ($x === false) + return 1; + } // TODO // merge with current record, current contents have priority // update record, set url-updated // update profile photos // schedule a scan? - + return 0; } -*/ + // handle friend suggestion notification @@ -2458,6 +2601,7 @@ function local_delivery($importer,$data) { $is_a_remote_delete = false; + // POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used? $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`, `contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id` @@ -2471,7 +2615,7 @@ function local_delivery($importer,$data) { intval($importer['importer_uid']) ); if($r && count($r)) - $is_a_remote_delete = true; + $is_a_remote_delete = true; // Does this have the characteristics of a community or private group comment? // If it's a reply to a wall post on a community/prvgroup page it's a @@ -2615,22 +2759,32 @@ function local_delivery($importer,$data) { // Specifically, the recipient? $is_a_remote_comment = false; - - // POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used? - $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`, - `contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item` - LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id` - WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s') - AND `item`.`uid` = %d - $sql_extra + $top_uri = $parent_uri; + + $r = q("select `item`.`parent-uri` from `item` + WHERE `item`.`uri` = '%s' LIMIT 1", - dbesc($parent_uri), - dbesc($parent_uri), - dbesc($parent_uri), - intval($importer['importer_uid']) + dbesc($parent_uri) ); - if($r && count($r)) - $is_a_remote_comment = true; + if($r && count($r)) { + $top_uri = $r[0]['parent-uri']; + + // POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used? + $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`, + `contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item` + LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s') + AND `item`.`uid` = %d + $sql_extra + LIMIT 1", + dbesc($top_uri), + dbesc($top_uri), + dbesc($top_uri), + intval($importer['importer_uid']) + ); + if($r && count($r)) + $is_a_remote_comment = true; + } // Does this have the characteristics of a community or private group comment? // If it's a reply to a wall post on a community/prvgroup page it's a @@ -2684,15 +2838,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']) @@ -2762,26 +2907,19 @@ 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; if($posted_id) { - $r = q("SELECT `parent` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", + $r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($posted_id), intval($importer['importer_uid']) ); - if(count($r)) + if(count($r)) { $parent = $r[0]['parent']; + $parent_uri = $r[0]['parent-uri']; + } if(! $is_like) { $r1 = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `uid` = %d AND `parent` = %d", @@ -2798,7 +2936,7 @@ function local_delivery($importer,$data) { } if($posted_id && $parent) { - + proc_run('php',"include/notifier.php","comment-import","$posted_id"); if((! $is_like) && (! $importer['self'])) { @@ -2821,7 +2959,7 @@ function local_delivery($importer,$data) { 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $parent, - + 'parent_uri' => $parent_uri, )); } @@ -2838,6 +2976,9 @@ 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`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), intval($importer['importer_uid']) @@ -2932,7 +3073,7 @@ function local_delivery($importer,$data) { if(!x($datarray['type']) || $datarray['type'] != 'activity') { $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0", - dbesc($parent_uri), + dbesc($top_uri), intval($importer['importer_uid']) ); @@ -2970,6 +3111,7 @@ function local_delivery($importer,$data) { 'verb' => ACTIVITY_POST, 'otype' => 'item', 'parent' => $conv_parent, + 'parent_uri' => $parent_uri )); @@ -3059,7 +3201,8 @@ function local_delivery($importer,$data) { $datarray['uid'] = $importer['importer_uid']; $datarray['contact-id'] = $importer['id']; - if(! link_compare($datarray['owner-link'],$contact['url'])) { + + if(! link_compare($datarray['owner-link'],$importer['url'])) { // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, // but otherwise there's a possible data mixup on the sender's system. // the tgroup delivery code called from item_store will correct it if it's a forum, @@ -3070,6 +3213,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)) { @@ -3143,7 +3289,7 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) { if(is_array($contact)) { if(($contact['network'] == NETWORK_OSTATUS && $contact['rel'] == CONTACT_IS_SHARING) || ($sharing && $contact['rel'] == CONTACT_IS_FOLLOWER)) { - $r = q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d AND `uid` = %d LIMIT 1", + $r = q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d LIMIT 1", intval(CONTACT_IS_FRIEND), intval($contact['id']), intval($importer['uid']) @@ -3328,7 +3474,6 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { else $body = $item['body']; - $o = "\r\n\r\n\r\n"; if(is_array($author)) @@ -3338,7 +3483,7 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { if(strlen($item['owner-name'])) $o .= atom_author('dfrn:owner',$item['owner-name'],$item['owner-link'],80,80,$item['owner-avatar']); - if(($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || ($item['thr-parent'])) { + if(($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) { $parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']); $o .= '' . "\r\n"; } @@ -3697,10 +3842,23 @@ function drop_item($id,$interactive = true) { $owner = $item['uid']; + $cid = 0; + // check if logged in user is either the author or owner of this item - if((local_user() == $item['uid']) || (remote_user() == $item['contact-id'])) { + if(is_array($_SESSION['remote'])) { + foreach($_SESSION['remote'] as $visitor) { + if($visitor['uid'] == $item['uid'] && $visitor['cid'] == $item['contact-id']) { + $cid = $visitor['cid']; + break; + } + } + } + + if((local_user() == $item['uid']) || ($cid) || (! $interactive)) { + + logger('delete item: ' . $item['id'], LOGGER_DEBUG); // delete the item $r = q("UPDATE `item` SET `deleted` = 1, `title` = '', `body` = '', `edited` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", @@ -3800,10 +3958,10 @@ function drop_item($id,$interactive = true) { // send the notification upstream/downstream as the case may be + proc_run('php',"include/notifier.php","drop","$drop_id"); + if(! $interactive) return $owner; - - proc_run('php',"include/notifier.php","drop","$drop_id"); goaway($a->get_baseurl() . '/' . $_SESSION['return_url']); //NOTREACHED }