X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fitems.php;h=0a8bc12c0893911e9e414acfb1d993949f8861b3;hb=91d1ef36d8e2bd117160418cb82a39c7b2353c91;hp=1bf73bc3604d5cd7e3facb6291086731fa981bb5;hpb=2abbd81ce1760cdfd4098ae1d5cda29e608eb021;p=friendica.git diff --git a/include/items.php b/include/items.php old mode 100755 new mode 100644 index 1bf73bc360..0a8bc12c08 --- a/include/items.php +++ b/include/items.php @@ -7,14 +7,11 @@ require_once('include/crypto.php'); function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) { - // default permissions - anonymous user - - if(! strlen($owner_nick)) - killme(); + $sitefeed = ((strlen($owner_nick)) ? false : true); // not yet implemented, need to rewrite huge chunks of following logic $public_feed = (($dfrn_id) ? false : true); - $starred = false; - $converse = false; + $starred = false; // not yet implemented, possible security issues + $converse = false; if($public_feed && $a->argc > 2) { for($x = 2; $x < $a->argc; $x++) { @@ -22,13 +19,20 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) $converse = true; if($a->argv[$x] == 'starred') $starred = true; + if($a->argv[$x] === 'category' && $a->argc > ($x + 1) && strlen($a->argv[$x+1])) + $category = $a->argv[$x+1]; } + + } + + + // default permissions - anonymous user $sql_extra = " AND `allow_cid` = '' AND `allow_gid` = '' AND `deny_cid` = '' AND `deny_gid` = '' "; - $r = q("SELECT `contact`.*, `user`.`uid` AS `user_uid`, `user`.`nickname`, `user`.`timezone` + $r = q("SELECT `contact`.*, `user`.`uid` AS `user_uid`, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags` FROM `contact` LEFT JOIN `user` ON `user`.`uid` = `contact`.`uid` WHERE `contact`.`self` = 1 AND `user`.`nickname` = '%s' LIMIT 1", dbesc($owner_nick) @@ -103,6 +107,10 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) if(! strlen($last_update)) $last_update = 'now -30 days'; + if(isset($category)) { + $sql_extra .= file_tag_file_query('item',$category,'category'); + } + if($public_feed) { if(! $converse) $sql_extra .= " AND `contact`.`self` = 1 "; @@ -156,7 +164,8 @@ function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) '$picdate' => xmlify(datetime_convert('UTC','UTC',$owner['avatar-date'] . '+00:00' , ATOM_TIME)) , '$uridate' => xmlify(datetime_convert('UTC','UTC',$owner['uri-date'] . '+00:00' , ATOM_TIME)) , '$namdate' => xmlify(datetime_convert('UTC','UTC',$owner['name-date'] . '+00:00' , ATOM_TIME)) , - '$birthday' => ((strlen($birthday)) ? '' . xmlify($birthday) . '' : '') + '$birthday' => ((strlen($birthday)) ? '' . xmlify($birthday) . '' : ''), + '$community' => (($owner['page-flags'] == PAGE_COMMUNITY) ? '1' : '') )); call_hooks('atom_feed', $atom); @@ -308,7 +317,7 @@ function get_atom_elements($feed,$item) { if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) { $base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']; foreach($base as $link) { - if(! $res['author-avatar']) { + if(!x($res, 'author-avatar') || !$res['author-avatar']) { if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') $res['author-avatar'] = unxmlify($link['attribs']['']['href']); } @@ -323,7 +332,7 @@ function get_atom_elements($feed,$item) { foreach($base as $link) { if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link'])) $res['author-link'] = unxmlify($link['attribs']['']['href']); - if(! $res['author-avatar']) { + if(!x($res, 'author-avatar') || !$res['author-avatar']) { if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo') $res['author-avatar'] = unxmlify($link['attribs']['']['href']); } @@ -417,7 +426,7 @@ function get_atom_elements($feed,$item) { // 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)) { + if((strpos($res['body'],'<') !== false) && (strpos($res['body'],'>') !== false)) { $res['body'] = reltoabs($res['body'],$base_url); @@ -430,14 +439,22 @@ function get_atom_elements($feed,$item) { // we shouldn't need a whitelist, because the bbcode converter // will strip out any unsupported tags. - // $config->set('HTML.Allowed', 'p,b,a[href],i'); $purifier = new HTMLPurifier($config); $res['body'] = $purifier->purify($res['body']); - $res['body'] = html2bbcode($res['body']); + $res['body'] = @html2bbcode($res['body']); + } + elseif(! $have_real_body) { + + // it's not one of our messages and it has no tags + // so it's probably just text. We'll escape it just to be safe. + + $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'); if($allow && $allow[0]['data'] == 1) $res['last-child'] = 1; @@ -503,7 +520,7 @@ function get_atom_elements($feed,$item) { $base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']; foreach($base as $link) { - if(! $res['owner-avatar']) { + if(!x($res, 'owner-avatar') || !$res['owner-avatar']) { if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar') $res['owner-avatar'] = unxmlify($link['attribs']['']['href']); } @@ -571,20 +588,21 @@ function get_atom_elements($feed,$item) { if($rawobj) { $res['object'] = '' . "\n"; - if($rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data']) { - $res['object-type'] = $rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data']; - $res['object'] .= '' . $rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '' . "\n"; + $child = $rawobj[0]['child']; + if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) { + $res['object-type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data']; + $res['object'] .= '' . $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '' . "\n"; } - if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data']) - $res['object'] .= '' . $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '' . "\n"; - if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) - $res['object'] .= '' . encode_rel_links($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) . '' . "\n"; - if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data']) - $res['object'] .= '' . $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '' . "\n"; - if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) { - $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']; + if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data']) + $res['object'] .= '' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '' . "\n"; + if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) + $res['object'] .= '' . encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) . '' . "\n"; + if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'title') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data']) + $res['object'] .= '' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '' . "\n"; + if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'content') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) { + $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']; if(! $body) - $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data']; + $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data']; // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events $res['object'] .= '' . xmlify($body) . '' . "\n"; if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) { @@ -609,20 +627,20 @@ function get_atom_elements($feed,$item) { if($rawobj) { $res['target'] = '' . "\n"; - if($rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data']) { - $res['target'] .= '' . $rawobj[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '' . "\n"; + $child = $rawobj[0]['child']; + if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) { + $res['target'] .= '' . $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '' . "\n"; } - if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data']) - $res['target'] .= '' . $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '' . "\n"; - - if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) - $res['target'] .= '' . encode_rel_links($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) . '' . "\n"; - if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data']) - $res['target'] .= '' . $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '' . "\n"; - if($rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) { - $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']; + if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data']) + $res['target'] .= '' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '' . "\n"; + if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) + $res['target'] .= '' . encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) . '' . "\n"; + if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'data') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data']) + $res['target'] .= '' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '' . "\n"; + if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'data') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) { + $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']; if(! $body) - $body = $rawobj[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data']; + $body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data']; // preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events $res['target'] .= '' . xmlify($body) . '' . "\n"; if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) { @@ -682,7 +700,7 @@ function item_store($arr,$force_parent = false) { unset($arr['dsprsig']); } - if($arr['gravity']) + if(x($arr, 'gravity')) $arr['gravity'] = intval($arr['gravity']); elseif($arr['parent-uri'] === $arr['uri']) $arr['gravity'] = 0; @@ -742,6 +760,7 @@ function item_store($arr,$force_parent = false) { if($arr['parent-uri'] === $arr['uri']) { $parent_id = 0; + $parent_deleted = 0; $allow_cid = $arr['allow_cid']; $allow_gid = $arr['allow_gid']; $deny_cid = $arr['deny_cid']; @@ -800,6 +819,8 @@ function item_store($arr,$force_parent = false) { logger('item_store: item parent was not found - ignoring item'); return 0; } + + $parent_deleted = 0; } } @@ -977,6 +998,7 @@ function tag_deliver($uid,$item_id) { 'language' => $u[0]['language'], 'to_name' => $u[0]['username'], 'to_email' => $u[0]['email'], + 'uid' => $u[0]['uid'], 'item' => $item, 'link' => $a->get_baseurl() . '/display/' . $u[0]['nickname'] . '/' . $item['id'], 'source_name' => $item['author-name'], @@ -1042,6 +1064,22 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { if(! $rino_enable) $rino = 0; + $ssl_val = intval(get_config('system','ssl_policy')); + $ssl_policy = ''; + + switch($ssl_val){ + case SSL_POLICY_FULL: + $ssl_policy = 'full'; + break; + case SSL_POLICY_SELFSIGN: + $ssl_policy = 'self'; + break; + case SSL_POLICY_NONE: + default: + $ssl_policy = 'none'; + break; + } + $url = $contact['notify'] . '&dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . (($rino) ? '&rino=1' : ''); logger('dfrn_deliver: ' . $url); @@ -1071,11 +1109,23 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $postvars = array(); $sent_dfrn_id = hex2bin((string) $res->dfrn_id); $challenge = hex2bin((string) $res->challenge); + $perm = (($res->perm) ? $res->perm : null); $dfrn_version = (float) (($res->dfrn_version) ? $res->dfrn_version : 2.0); $rino_allowed = ((intval($res->rino) === 1) ? 1 : 0); + $page = (($owner['page-flags'] == PAGE_COMMUNITY) ? 1 : 0); $final_dfrn_id = ''; + if($perm) { + if((($perm == 'rw') && (! intval($contact['writable']))) + || (($perm == 'r') && (intval($contact['writable'])))) { + q("update contact set writable = %d where id = %d limit 1", + intval(($perm == 'rw') ? 1 : 0), + intval($contact['id']) + ); + $contact['writable'] = (string) 1 - intval($contact['writable']); + } + } if(($contact['duplex'] && strlen($contact['pubkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey'])) @@ -1114,6 +1164,11 @@ function dfrn_deliver($owner,$contact,$atom, $dissolve = false) { $postvars['perm'] = 'r'; } + $postvars['ssl_policy'] = $ssl_policy; + + if($page) + $postvars['page'] = '1'; + if($rino && $rino_allowed && (! $dissolve)) { $key = substr(random_string(),0,16); $data = bin2hex(aes_encrypt($postvars['data'],$key)); @@ -1307,12 +1362,28 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } if((is_array($contact)) && ($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) { - q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1", + $r = q("select * from contact where uid = %d and id = %d limit 1", + intval($contact['uid']), + intval($contact['id']) + ); + + $x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc(notags(trim($new_name))), dbesc(datetime_convert()), intval($contact['uid']), intval($contact['id']) ); + + // do our best to update the name on content items + + if(count($r)) { + q("update item set `author-name` = '%s' where `author-name` = '%s' and `author-link` = '%s' and uid = %d", + dbesc(notags(trim($new_name))), + dbesc($r[0]['name']), + dbesc($r[0]['url']), + intval($contact['uid']) + ); + } } if(strlen($birthday)) { @@ -1362,6 +1433,19 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } + $community_page = 0; + $rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'community'); + if($rawtags) { + $community_page = intval($rawtags[0]['data']); + } + if(is_array($contact) && intval($contact['forum']) != $community_page) { + q("update contact set forum = %d where id = %d limit 1", + intval($community_page), + intval($contact['id']) + ); + $contact['forum'] = (string) $community_page; + } + // process any deleted entries @@ -1381,7 +1465,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } if($deleted && is_array($contact)) { $r = q("SELECT `item`.*, `contact`.`self` FROM `item` left join `contact` on `item`.`contact-id` = `contact`.`id` - WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d LIMIT 1", + WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1", dbesc($uri), intval($importer['uid']), intval($contact['id']) @@ -1392,7 +1476,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if(! $item['deleted']) logger('consume_feed: deleting item ' . $item['id'] . ' uri=' . $item['uri'], LOGGER_DEBUG); - if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTVITY_OBJ_TAGTERM)) { + if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTIVITY_OBJ_TAGTERM)) { $xo = parse_xml_string($item['object'],false); $xt = parse_xml_string($item['target'],false); if($xt->type === ACTIVITY_OBJ_NOTE) { @@ -1504,13 +1588,18 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) $item_id = $item->get_id(); $datarray = get_atom_elements($feed,$item); - if(! x($datarray,'author-name')) + + if((! x($datarray,'author-name')) && ($contact['network'] != NETWORK_DFRN)) $datarray['author-name'] = $contact['name']; - if(! x($datarray,'author-link')) + if((! x($datarray,'author-link')) && ($contact['network'] != NETWORK_DFRN)) $datarray['author-link'] = $contact['url']; - if(! x($datarray,'author-avatar')) + if((! x($datarray,'author-avatar')) && ($contact['network'] != NETWORK_DFRN)) $datarray['author-avatar'] = $contact['thumb']; + if((! x($datarray,'author-name')) || (! x($datarray,'author-link'))) { + logger('consume_feed: no author information! ' . print_r($datarray,true)); + continue; + } $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($item_id), @@ -1521,9 +1610,10 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if(count($r)) { if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { - $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($datarray['title']), dbesc($datarray['body']), + dbesc($datarray['tag']), dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), dbesc($item_id), intval($importer['uid']) @@ -1550,8 +1640,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } $force_parent = false; - if($contact['network'] === NETWORK_OSTATUS) { - $force_parent = true; + if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) { + if($contact['network'] === NETWORK_OSTATUS) + $force_parent = true; if(strlen($datarray['title'])) unset($datarray['title']); $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", @@ -1572,6 +1663,14 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if((activity_match($datarray['verb'],ACTIVITY_LIKE)) || (activity_match($datarray['verb'],ACTIVITY_DISLIKE))) { $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; + // only one like or dislike per person + $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1", + intval($datarray['uid']), + intval($datarray['contact-id']), + dbesc($datarray['verb']) + ); + if($r && count($r)) + continue; } if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) { @@ -1612,14 +1711,19 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) $datarray = get_atom_elements($feed,$item); if(is_array($contact)) { - if(! x($datarray,'author-name')) + if((! x($datarray,'author-name')) && ($contact['network'] != NETWORK_DFRN)) $datarray['author-name'] = $contact['name']; - if(! x($datarray,'author-link')) + if((! x($datarray,'author-link')) && ($contact['network'] != NETWORK_DFRN)) $datarray['author-link'] = $contact['url']; - if(! x($datarray,'author-avatar')) + if((! x($datarray,'author-avatar')) && ($contact['network'] != NETWORK_DFRN)) $datarray['author-avatar'] = $contact['thumb']; } + if((! x($datarray,'author-name')) || (! x($datarray,'author-link'))) { + logger('consume_feed: no author information! ' . print_r($datarray,true)); + continue; + } + // special handling for events if((x($datarray,'object-type')) && ($datarray['object-type'] === ACTIVITY_OBJ_EVENT)) { @@ -1652,9 +1756,10 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if(count($r)) { if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { - $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($datarray['title']), dbesc($datarray['body']), + dbesc($datarray['tag']), dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), dbesc($item_id), intval($importer['uid']) @@ -1699,7 +1804,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if(! is_array($contact)) return; - if($contact['network'] === NETWORK_OSTATUS || stristr($permalink,'twitter.com')) { + if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) { if(strlen($datarray['title'])) unset($datarray['title']); $datarray['last-child'] = 1; @@ -1719,6 +1824,18 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) $datarray['parent-uri'] = $item_id; $datarray['uid'] = $importer['uid']; $datarray['contact-id'] = $contact['id']; + + if(! link_compare($datarray['owner-link'],$contact['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, + // but we're going to unconditionally correct it here so that the post will always be owned by our contact. + logger('consume_feed: Correcting item owner.', LOGGER_DEBUG); + $datarray['owner-name'] = $contact['name']; + $datarray['owner-link'] = $contact['url']; + $datarray['owner-avatar'] = $contact['thumb']; + } + $r = item_store($datarray); continue; @@ -1750,6 +1867,8 @@ function local_delivery($importer,$data) { $feed->enable_order_by_date(false); $feed->init(); +/* + // Currently unsupported - needs a lot of work $reloc = $feed->get_feed_tags( NAMESPACE_DFRN, 'relocate' ); if(isset($reloc[0]['child'][NAMESPACE_DFRN])) { $base = $reloc[0]['child'][NAMESPACE_DFRN]; @@ -1774,6 +1893,7 @@ function local_delivery($importer,$data) { // schedule a scan? } +*/ // handle friend suggestion notification @@ -1809,6 +1929,14 @@ function local_delivery($importer,$data) { ); if(count($r)) { $fid = $r[0]['id']; + + // OK, we do. Do we already have an introduction for this person ? + $r = q("select id from intro where uid = %d and fid = %d limit 1", + intval($fsugg['uid']), + intval($fid) + ); + if(count($r)) + return 0; } if(! $fid) $r = q("INSERT INTO `fcontact` ( `name`,`url`,`photo`,`request` ) VALUES ( '%s', '%s', '%s', '%s' ) ", @@ -1829,6 +1957,7 @@ function local_delivery($importer,$data) { else return 0; + $hash = random_string(); $r = q("INSERT INTO `intro` ( `uid`, `fid`, `contact-id`, `note`, `hash`, `datetime`, `blocked` ) @@ -1848,6 +1977,7 @@ function local_delivery($importer,$data) { 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], + 'uid' => $importer['importer_uid'], 'item' => $fsugg, 'link' => $a->get_baseurl() . '/notifications/intros', 'source_name' => $importer['name'], @@ -1899,6 +2029,7 @@ function local_delivery($importer,$data) { 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], + 'uid' => $importer['importer_uid'], 'item' => $msg, 'source_name' => $msg['from-name'], 'source_link' => $importer['url'], @@ -1912,6 +2043,19 @@ function local_delivery($importer,$data) { // NOTREACHED } + + $community_page = 0; + $rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'community'); + if($rawtags) { + $community_page = intval($rawtags[0]['data']); + } + if(intval($importer['forum']) != $community_page) { + q("update contact set forum = %d where id = %d limit 1", + intval($community_page), + intval($importer['id']) + ); + $importer['forum'] = (string) $community_page; + } logger('local_delivery: feed item count = ' . $feed->get_item_quantity()); @@ -1934,7 +2078,7 @@ function local_delivery($importer,$data) { if($deleted) { $r = q("SELECT `item`.*, `contact`.`self` FROM `item` left join contact on `item`.`contact-id` = `contact`.`id` - WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d LIMIT 1", + WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1", dbesc($uri), intval($importer['importer_uid']), intval($importer['id']) @@ -1948,9 +2092,10 @@ function local_delivery($importer,$data) { logger('local_delivery: deleting item ' . $item['id'] . ' uri=' . $item['uri'], LOGGER_DEBUG); - if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTVITY_OBJ_TAGTERM)) { + if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTIVITY_OBJ_TAGTERM)) { $xo = parse_xml_string($item['object'],false); $xt = parse_xml_string($item['target'],false); + if($xt->type === ACTIVITY_OBJ_NOTE) { $i = q("select * from `item` where uri = '%s' and uid = %d limit 1", dbesc($xt->id), @@ -2037,13 +2182,12 @@ function local_delivery($importer,$data) { } if($is_reply) { - $community = false; if($importer['page-flags'] == PAGE_COMMUNITY) { $sql_extra = ''; $community = true; - logger('local_delivery: community reply'); + logger('local_delivery: possible community reply'); } else $sql_extra = " and contact.self = 1 and item.wall = 1 "; @@ -2051,7 +2195,9 @@ function local_delivery($importer,$data) { // was the top-level post for this reply written by somebody on this site? // Specifically, the recipient? - $r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, + $is_a_remote_comment = false; + + $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' @@ -2062,16 +2208,57 @@ function local_delivery($importer,$data) { dbesc($parent_uri), intval($importer['importer_uid']) ); + if($r && count($r)) + $is_a_remote_comment = true; + + // Does this have the characteristics of a community comment? + // If it's a reply to a wall post on a community page it's a + // valid community comment. Also forum_mode makes it valid for sure. + // If neither, it's not. + + if($is_a_remote_comment && $community) { + if((! $r[0]['forum_mode']) && (! $r[0]['wall'])) { + $is_a_remote_comment = false; + logger('local_delivery: not a community reply'); + } + } - if($r && count($r)) { - + if($is_a_remote_comment) { logger('local_delivery: received remote comment'); $is_like = false; // remote reply to our post. Import and then notify everybody else. $datarray = get_atom_elements($feed,$item); - // TODO: make this next part work against both delivery threads of a community post + $r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + dbesc($item_id), + intval($importer['importer_uid']) + ); + + // Update content if 'updated' changes + + if(count($r)) { + $iid = $r[0]['id']; + if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { + logger('received updated comment' , LOGGER_DEBUG); + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + dbesc($datarray['title']), + dbesc($datarray['body']), + dbesc($datarray['tag']), + dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), + dbesc($item_id), + intval($importer['importer_uid']) + ); + + proc_run('php',"include/notifier.php","comment-import",$iid); + + } + + continue; + } + + + // 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'] ); @@ -2092,6 +2279,14 @@ function local_delivery($importer,$data) { $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; $datarray['last-child'] = 0; + // only one like or dislike per person + $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1", + intval($datarray['uid']), + intval($datarray['contact-id']), + dbesc($datarray['verb']) + ); + if($r && count($r)) + continue; } if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) { @@ -2171,6 +2366,7 @@ function local_delivery($importer,$data) { 'language' => $importer['language'], 'to_name' => $importer['username'], 'to_email' => $importer['email'], + 'uid' => $importer['importer_uid'], 'item' => $datarray, 'link' => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $posted_id, 'source_name' => stripslashes($datarray['author-name']), @@ -2178,12 +2374,14 @@ function local_delivery($importer,$data) { 'source_photo' => ((link_compare($datarray['author-link'],$importer['url'])) ? $importer['thumb'] : $datarray['author-avatar']), 'verb' => ACTIVITY_POST, - 'otype' => 'item' + 'otype' => 'item', + 'parent' => $parent, )); } } + return 0; // NOTREACHED } @@ -2204,9 +2402,10 @@ function local_delivery($importer,$data) { if(count($r)) { if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { - $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($datarray['title']), dbesc($datarray['body']), + dbesc($datarray['tag']), dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), dbesc($item_id), intval($importer['importer_uid']) @@ -2238,6 +2437,15 @@ function local_delivery($importer,$data) { if(($datarray['verb'] == ACTIVITY_LIKE) || ($datarray['verb'] == ACTIVITY_DISLIKE)) { $datarray['type'] = 'activity'; $datarray['gravity'] = GRAVITY_LIKE; + // only one like or dislike per person + $r = q("select id from item where uid = %d and `contact-id` = %d and verb ='%s' and deleted = 0 limit 1", + intval($datarray['uid']), + intval($datarray['contact-id']), + dbesc($datarray['verb']) + ); + if($r && count($r)) + continue; + } if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) { @@ -2269,40 +2477,53 @@ function local_delivery($importer,$data) { // find out if our user is involved in this conversation and wants to be notified. - if($datarray['type'] != 'activity') { + if(!x($datarray['type']) || $datarray['type'] != 'activity') { - $myconv = q("SELECT `author-link`, `author-avatar` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 ", + $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 ", dbesc($parent_uri), intval($importer['importer_uid']) ); if(count($myconv)) { $importer_url = $a->get_baseurl() . '/profile/' . $importer['nickname']; - foreach($myconv as $conv) { - if(! link_compare($conv['author-link'],$importer_url)) - continue; + // first make sure this isn't our own post coming back to us from a wall-to-wall event + if(! link_compare($datarray['author-link'],$importer_url)) { - require_once('include/enotify.php'); + + foreach($myconv as $conv) { - notification(array( - 'type' => NOTIFY_COMMENT, - 'notify_flags' => $importer['notify-flags'], - 'language' => $importer['language'], - 'to_name' => $importer['username'], - 'to_email' => $importer['email'], - 'item' => $datarray, - 'link' => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $posted_id, - 'source_name' => stripslashes($datarray['author-name']), - 'source_link' => $datarray['author-link'], - 'source_photo' => ((link_compare($datarray['author-link'],$importer['url'])) - ? $importer['thumb'] : $datarray['author-avatar']), - 'verb' => ACTIVITY_POST, - 'otype' => 'item' - - )); + // now if we find a match, it means we're in this conversation + + if(! link_compare($conv['author-link'],$importer_url)) + continue; - break; + require_once('include/enotify.php'); + + $conv_parent = $conv['parent']; + + notification(array( + 'type' => NOTIFY_COMMENT, + 'notify_flags' => $importer['notify-flags'], + 'language' => $importer['language'], + 'to_name' => $importer['username'], + 'to_email' => $importer['email'], + 'uid' => $importer['importer_uid'], + 'item' => $datarray, + 'link' => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $posted_id, + 'source_name' => stripslashes($datarray['author-name']), + 'source_link' => $datarray['author-link'], + 'source_photo' => ((link_compare($datarray['author-link'],$importer['url'])) + ? $importer['thumb'] : $datarray['author-avatar']), + 'verb' => ACTIVITY_POST, + 'otype' => 'item', + 'parent' => $conv_parent, + + )); + + // only send one notification + break; + } } } } @@ -2347,9 +2568,10 @@ function local_delivery($importer,$data) { if(count($r)) { if((x($datarray,'edited') !== false) && (datetime_convert('UTC','UTC',$datarray['edited']) !== $r[0]['edited'])) { - $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s' WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($datarray['title']), dbesc($datarray['body']), + dbesc($datarray['tag']), dbesc(datetime_convert('UTC','UTC',$datarray['edited'])), dbesc($item_id), intval($importer['importer_uid']) @@ -2373,12 +2595,24 @@ function local_delivery($importer,$data) { // This is my contact on another system, but it's really me. // Turn this into a wall post. - if($contact['remote_self']) + if($importer['remote_self']) $datarray['wall'] = 1; $datarray['parent-uri'] = $item_id; $datarray['uid'] = $importer['importer_uid']; $datarray['contact-id'] = $importer['id']; + + if(! link_compare($datarray['owner-link'],$contact['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, + // but we're going to unconditionally correct it here so that the post will always be owned by our contact. + logger('local_delivery: Correcting item owner.', LOGGER_DEBUG); + $datarray['owner-name'] = $importer['senderName']; + $datarray['owner-link'] = $importer['url']; + $datarray['owner-avatar'] = $importer['thumb']; + } + $r = item_store($datarray); continue; } @@ -2763,6 +2997,11 @@ function item_expire($uid,$days) { foreach($r as $item) { + // don't expire filed items + + if(strpos($item['file'],'[') !== false) + continue; + // Only expire posts, not photos and photo comments if($expire_photos==0 && strlen($item['resource-id'])) @@ -2774,12 +3013,23 @@ function item_expire($uid,$days) { if($expire_items==0 && $item['type']!='note') continue; + $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `id` = %d LIMIT 1", dbesc(datetime_convert()), dbesc(datetime_convert()), intval($item['id']) ); + $r = q("DELETE FROM item_id where iid in (select id from item where parent = %d) and uid = %d", + intval($item['id']), + intval($uid) + ); + + $r = q("DELETE FROM sign where iid in (select id from item where parent = %d) and uid = %d", + intval($item['id']), + intval($uid) + ); + // kill the kids $r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ", @@ -2799,7 +3049,7 @@ function item_expire($uid,$days) { function drop_items($items) { $uid = 0; - if((! local_user()) && (! $remote_user())) + if(! local_user() && ! remote_user()) return; if(count($items)) {