X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fitems.php;h=fb357d4db7b41c12e3d9d4c57888db28b780ea21;hb=3c8fc863a8163632e193849ad90e6bc7be68b6f0;hp=2d6109b0f2884467368a41bb08297df71d4e18c3;hpb=0c1fdb7da182485435576af98e2ab8d777ab017a;p=friendica.git diff --git a/include/items.php b/include/items.php index 2d6109b0f2..fb357d4db7 100644 --- a/include/items.php +++ b/include/items.php @@ -11,6 +11,7 @@ require_once('include/text.php'); require_once('include/email.php'); require_once('include/ostatus_conversation.php'); require_once('include/threads.php'); +require_once('include/socgraph.php'); function get_feed_for(&$a, $dfrn_id, $owner_nick, $last_update, $direction = 0) { @@ -872,9 +873,19 @@ function get_atom_elements($feed, $item, $contact = array()) { } if (isset($contact["network"]) AND ($contact["network"] == NETWORK_FEED) AND $contact['fetch_further_information']) { - $res["body"] = $res["title"].add_page_info($res['plink'], false, "", true); + $preview = ""; + + // Handle enclosures and treat them as preview picture + if (isset($attach)) + foreach ($attach AS $attachment) + if ($attachment->type == "image/jpeg") + $preview = $attachment->link; + + $res["body"] = $res["title"].add_page_info($res['plink'], false, $preview, ($contact['fetch_further_information'] == 2), $contact['ffi_keyword_blacklist']); + $res["tag"] = add_page_keywords($res['plink'], false, $preview, ($contact['fetch_further_information'] == 2), $contact['ffi_keyword_blacklist']); $res["title"] = ""; $res["object-type"] = ACTIVITY_OBJ_BOOKMARK; + unset($res["attach"]); } elseif (isset($contact["network"]) AND ($contact["network"] == NETWORK_OSTATUS)) $res["body"] = add_page_info_to_body($res["body"]); elseif (isset($contact["network"]) AND ($contact["network"] == NETWORK_FEED) AND strstr($res['plink'], ".app.net/")) { @@ -903,6 +914,12 @@ function add_page_info_data($data) { if ($no_photos AND ($data["type"] == "photo")) return(""); + // If the link contains BBCode stuff, make a short link out of this to avoid parsing problems + if (strpos($data["url"], '[') OR strpos($data["url"], ']')) { + require_once("include/network.php"); + $data["url"] = short_link($data["url"]); + } + if (($data["type"] != "photo") AND is_string($data["title"])) $text .= "[bookmark=".$data["url"]."]".trim($data["title"])."[/bookmark]"; @@ -921,7 +938,8 @@ function add_page_info_data($data) { $a = get_app(); $hashtags = "\n"; foreach ($data["keywords"] AS $keyword) { - $hashtag = str_replace(" ", "", $keyword); + $hashtag = str_replace(array(" ", "+", "/", ".", "#", "'"), + array("","", "", "", "", ""), $keyword); $hashtags .= "#[url=".$a->get_baseurl()."/search?tag=".rawurlencode($hashtag)."]".$hashtag."[/url] "; } } @@ -929,16 +947,60 @@ function add_page_info_data($data) { return("\n[class=type-".$data["type"]."]".$text."[/class]".$hashtags); } -function add_page_info($url, $no_photos = false, $photo = "", $keywords = false) { +function query_page_info($url, $no_photos = false, $photo = "", $keywords = false, $keyword_blacklist = "") { require_once("mod/parse_url.php"); - $data = parseurl_getsiteinfo($url, true); + $data = Cache::get("parse_url:".$url); + if (is_null($data)){ + $data = parseurl_getsiteinfo($url, true); + Cache::set("parse_url:".$url,serialize($data)); + } else + $data = unserialize($data); + + if ($photo != "") + $data["images"][0]["src"] = $photo; - logger('add_page_info: fetch page info for '.$url.' '.print_r($data, true), LOGGER_DEBUG); + logger('fetch page info for '.$url.' '.print_r($data, true), LOGGER_DEBUG); if (!$keywords AND isset($data["keywords"])) unset($data["keywords"]); + if (($keyword_blacklist != "") AND isset($data["keywords"])) { + $list = explode(",", $keyword_blacklist); + foreach ($list AS $keyword) { + $keyword = trim($keyword); + $index = array_search($keyword, $data["keywords"]); + if ($index !== false) + unset($data["keywords"][$index]); + } + } + + return($data); +} + +function add_page_keywords($url, $no_photos = false, $photo = "", $keywords = false, $keyword_blacklist = "") { + $data = query_page_info($url, $no_photos, $photo, $keywords, $keyword_blacklist); + + $tags = ""; + if (isset($data["keywords"]) AND count($data["keywords"])) { + $a = get_app(); + foreach ($data["keywords"] AS $keyword) { + $hashtag = str_replace(array(" ", "+", "/", ".", "#", "'"), + array("","", "", "", "", ""), $keyword); + + if ($tags != "") + $tags .= ","; + + $tags .= "#[url=".$a->get_baseurl()."/search?tag=".rawurlencode($hashtag)."]".$hashtag."[/url]"; + } + } + + return($tags); +} + +function add_page_info($url, $no_photos = false, $photo = "", $keywords = false, $keyword_blacklist = "") { + $data = query_page_info($url, $no_photos, $photo, $keywords, $keyword_blacklist); + $text = add_page_info_data($data); return($text); @@ -1010,7 +1072,7 @@ function encode_rel_links($links) { -function item_store($arr,$force_parent = false, $notify = false) { +function item_store($arr,$force_parent = false, $notify = false, $dontcache = false) { // If it is a posting where users should get notifications, then define it as wall posting if ($notify) { @@ -1150,6 +1212,11 @@ function item_store($arr,$force_parent = false, $notify = false) { $arr['origin'] = ((x($arr,'origin')) ? intval($arr['origin']) : 0 ); $arr['guid'] = ((x($arr,'guid')) ? notags(trim($arr['guid'])) : get_guid(30)); $arr['network'] = ((x($arr,'network')) ? trim($arr['network']) : ''); + $arr['postopts'] = ((x($arr,'postopts')) ? trim($arr['postopts']) : ''); + $arr['resource-id'] = ((x($arr,'resource-id')) ? trim($arr['resource-id']) : ''); + $arr['event-id'] = ((x($arr,'event-id')) ? intval($arr['event-id']) : 0 ); + $arr['inform'] = ((x($arr,'inform')) ? trim($arr['inform']) : ''); + $arr['file'] = ((x($arr,'file')) ? trim($arr['file']) : ''); if ($arr['plink'] == "") { $a = get_app(); @@ -1283,6 +1350,9 @@ function item_store($arr,$force_parent = false, $notify = false) { return 0; } + // Store the unescaped version + $unescaped = $arr; + dbesc_array($arr); logger('item_store: ' . print_r($arr,true), LOGGER_DATA); @@ -1293,10 +1363,12 @@ function item_store($arr,$force_parent = false, $notify = false) { . implode("', '", array_values($arr)) . "')" ); - // find the item we just created + // And restore it + $arr = $unescaped; + // find the item we just created $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d ORDER BY `id` ASC ", - $arr['uri'], // already dbesc'd + dbesc($arr['uri']), intval($arr['uid']) ); @@ -1304,49 +1376,25 @@ function item_store($arr,$force_parent = false, $notify = false) { $current_post = $r[0]['id']; logger('item_store: created item ' . $current_post); - // Only check for notifications on start posts - if ($arr['parent-uri'] === $arr['uri']) { - add_thread($r[0]['id']); - logger('item_store: Check notification for contact '.$arr['contact-id'].' and post '.$current_post, LOGGER_DEBUG); + // Add every contact to the global contact table + // Contacts from the statusnet connector are also added since you could add them in OStatus as well. + if (!$arr['private'] AND in_array($arr["network"], + array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_STATUSNET, ""))) { + poco_check($arr["author-link"], $arr["author-name"], $arr["network"], $arr["author-avatar"], "", "", "", "", "", $arr["received"], $arr["contact-id"], $arr["uid"]); - // Send a notification for every new post? - $r = q("SELECT `notify_new_posts` FROM `contact` WHERE `id` = %d AND `uid` = %d AND `notify_new_posts` LIMIT 1", - intval($arr['contact-id']), - intval($arr['uid']) - ); - - if(count($r)) { - logger('item_store: Send notification for contact '.$arr['contact-id'].' and post '.$current_post, LOGGER_DEBUG); - $u = q("SELECT * FROM user WHERE uid = %d LIMIT 1", - intval($arr['uid'])); - - $item = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d", - intval($current_post), - intval($arr['uid']) - ); - - $a = get_app(); - - require_once('include/enotify.php'); - notification(array( - 'type' => NOTIFY_SHARE, - 'notify_flags' => $u[0]['notify-flags'], - 'language' => $u[0]['language'], - 'to_name' => $u[0]['username'], - 'to_email' => $u[0]['email'], - 'uid' => $u[0]['uid'], - 'item' => $item[0], - 'link' => $a->get_baseurl().'/display/'.urlencode($arr['guid']), - 'source_name' => $item[0]['author-name'], - 'source_link' => $item[0]['author-link'], - 'source_photo' => $item[0]['author-avatar'], - 'verb' => ACTIVITY_TAG, - 'otype' => 'item' - )); - logger('item_store: Notification sent for contact '.$arr['contact-id'].' and post '.$current_post, LOGGER_DEBUG); - } + // Maybe its a body with a shared item? Then extract a global contact from it. + poco_contact_from_body($arr["body"], $arr["received"], $arr["contact-id"], $arr["uid"]); } + // Set "success_update" to the date of the last time we heard from this contact + // This can be used to filter for inactive contacts and poco. + // Only do this for public postings to avoid privacy problems, since poco data is public. + // Don't set this value if it isn't from the owner (could be an author that we don't know) + if (!$arr['private'] AND (($arr["author-link"] === $arr["owner-link"]) OR ($arr["parent-uri"] === $arr["uri"]))) + q("UPDATE `contact` SET `success_update` = '%s' WHERE `id` = %d", + dbesc($arr['received']), + intval($arr['contact-id']) + ); } else { logger('item_store: could not locate created item'); return 0; @@ -1354,7 +1402,7 @@ function item_store($arr,$force_parent = false, $notify = false) { if(count($r) > 1) { logger('item_store: duplicated post occurred. Removing duplicates.'); q("DELETE FROM `item` WHERE `uri` = '%s' AND `uid` = %d AND `id` != %d ", - $arr['uri'], + dbesc($arr['uri']), intval($arr['uid']), intval($current_post) ); @@ -1402,7 +1450,6 @@ function item_store($arr,$force_parent = false, $notify = false) { dbesc(datetime_convert()), intval($parent_id) ); - update_thread($parent_id); if($dsprsig) { q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ", @@ -1430,19 +1477,10 @@ function item_store($arr,$force_parent = false, $notify = false) { // current post can be deleted if is for a communuty page and no mention are // in it. - if (!$deleted) { + if (!$deleted AND !$dontcache) { // Store the fresh generated item into the cache - $cachefile = get_cachefile(urlencode($arr["guid"])."-".hash("md5", $arr['body'])); - - if (($cachefile != '') AND !file_exists($cachefile)) { - $s = prepare_text($arr['body']); - $a = get_app(); - $stamp1 = microtime(true); - file_put_contents($cachefile, $s); - $a->save_timestamp($stamp1, "file"); - logger('item_store: put item '.$current_post.' into cachefile '.$cachefile); - } + put_item_in_cache($arr); $r = q('SELECT * FROM `item` WHERE id = %d', intval($current_post)); if (count($r) == 1) { @@ -1455,6 +1493,65 @@ function item_store($arr,$force_parent = false, $notify = false) { create_tags_from_item($current_post); create_files_from_item($current_post); + // Only check for notifications on start posts + if ($arr['parent-uri'] === $arr['uri']) { + add_thread($current_post); + logger('item_store: Check notification for contact '.$arr['contact-id'].' and post '.$current_post, LOGGER_DEBUG); + + // Send a notification for every new post? + $r = q("SELECT `notify_new_posts` FROM `contact` WHERE `id` = %d AND `uid` = %d AND `notify_new_posts` LIMIT 1", + intval($arr['contact-id']), + intval($arr['uid']) + ); + $send_notification = count($r); + + if (!$send_notification) { + $tags = q("SELECT `url` FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` = %d AND `uid` = %d", + intval(TERM_OBJ_POST), intval($current_post), intval(TERM_MENTION), intval($arr['uid'])); + + if (count($tags)) { + foreach ($tags AS $tag) { + $r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `notify_new_posts`", + normalise_link($tag["url"]), intval($arr['uid'])); + if (count($r)) + $send_notification = true; + } + } + } + + if ($send_notification) { + logger('item_store: Send notification for contact '.$arr['contact-id'].' and post '.$current_post, LOGGER_DEBUG); + $u = q("SELECT * FROM user WHERE uid = %d LIMIT 1", + intval($arr['uid'])); + + $item = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d", + intval($current_post), + intval($arr['uid']) + ); + + $a = get_app(); + + require_once('include/enotify.php'); + notification(array( + 'type' => NOTIFY_SHARE, + 'notify_flags' => $u[0]['notify-flags'], + 'language' => $u[0]['language'], + 'to_name' => $u[0]['username'], + 'to_email' => $u[0]['email'], + 'uid' => $u[0]['uid'], + 'item' => $item[0], + 'link' => $a->get_baseurl().'/display/'.urlencode($arr['guid']), + 'source_name' => $item[0]['author-name'], + 'source_link' => $item[0]['author-link'], + 'source_photo' => $item[0]['author-avatar'], + 'verb' => ACTIVITY_TAG, + 'otype' => 'item' + )); + logger('item_store: Notification sent for contact '.$arr['contact-id'].' and post '.$current_post, LOGGER_DEBUG); + } + } else + update_thread($parent_id); + if ($notify) proc_run('php', "include/notifier.php", $notify_type, $current_post); @@ -2001,9 +2098,16 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) if($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) { $name_updated = $elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']; $new_name = $elems['name'][0]['data']; + + // Manually checking for changed contact names + if (($new_name != $contact['name']) AND ($new_name != "") AND ($name_updated <= $contact['name-date'])) { + $name_updated = date("c"); + $photo_timestamp = date("c"); + } } if((x($elems,'link')) && ($elems['link'][0]['attribs']['']['rel'] === 'photo') && ($elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated'])) { - $photo_timestamp = datetime_convert('UTC','UTC',$elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']); + if ($photo_timestamp == "") + $photo_timestamp = datetime_convert('UTC','UTC',$elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']); $photo_url = $elems['link'][0]['attribs']['']['href']; } @@ -2598,45 +2702,84 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) // This is my contact on another system, but it's really me. // Turn this into a wall post. + $notify = item_is_remote_self($contact, $datarray); - if($contact['remote_self']) { - if ($contact['remote_self'] == 2) { - $r = q("SELECT `id`,`url`,`name`,`photo`,`network` FROM `contact` WHERE `uid` = %d AND `self`", intval($importer['uid'])); - if (count($r)) { - $datarray['contact-id'] = $r[0]["id"]; + $r = item_store($datarray, false, $notify); + logger('Stored - Contact '.$contact['url'].' Notify '.$notify.' return '.$r.' Item '.print_r($datarray, true), LOGGER_DEBUG); + continue; - $datarray['owner-name'] = $r[0]["name"]; - $datarray['owner-link'] = $r[0]["url"]; - $datarray['owner-avatar'] = $r[0]["photo"]; + } + } + } +} - $datarray['author-name'] = $datarray['owner-name']; - $datarray['author-link'] = $datarray['owner-link']; - $datarray['author-avatar'] = $datarray['owner-avatar']; - } - } +function item_is_remote_self($contact, &$datarray) { + $a = get_app(); - if (!isset($datarray["app"]) OR ($datarray["app"] == "")) - $datarray["app"] = network_to_name($contact['network']); + if (!$contact['remote_self']) + return false; - $notify = true; - if($contact['network'] === NETWORK_FEED) { - $datarray['private'] = 0; - } - } else - $notify = false; + // Prevent the forwarding of posts that are forwarded + if ($datarray["extid"] == NETWORK_DFRN) + return false; - $r = item_store($datarray, false, $notify); - continue; + // Prevent to forward already forwarded posts + if ($datarray["app"] == $a->get_hostname()) + return false; - } + // Only forward posts + if ($datarray["verb"] != ACTIVITY_POST) + return false; + + if (($contact['network'] != NETWORK_FEED) AND $datarray['private']) + return false; + + $datarray2 = $datarray; + logger('remote-self start - Contact '.$contact['url'].' - '.$contact['remote_self'].' Item '.print_r($datarray, true), LOGGER_DEBUG); + if ($contact['remote_self'] == 2) { + $r = q("SELECT `id`,`url`,`name`,`thumb` FROM `contact` WHERE `uid` = %d AND `self`", + intval($contact['uid'])); + if (count($r)) { + $datarray['contact-id'] = $r[0]["id"]; + + $datarray['owner-name'] = $r[0]["name"]; + $datarray['owner-link'] = $r[0]["url"]; + $datarray['owner-avatar'] = $r[0]["thumb"]; + + $datarray['author-name'] = $datarray['owner-name']; + $datarray['author-link'] = $datarray['owner-link']; + $datarray['author-avatar'] = $datarray['owner-avatar']; } + + if ($contact['network'] != NETWORK_FEED) { + $datarray["guid"] = get_guid(32); + unset($datarray["plink"]); + $datarray["uri"] = item_new_uri($a->get_hostname(),$contact['uid']); + $datarray["parent-uri"] = $datarray["uri"]; + $datarray["extid"] = $contact['network']; + $urlpart = parse_url($datarray2['author-link']); + $datarray["app"] = $urlpart["host"]; + } else + $datarray['private'] = 0; } + + //if (!isset($datarray["app"]) OR ($datarray["app"] == "")) + // $datarray["app"] = network_to_name($contact['network']); + + if ($contact['network'] != NETWORK_FEED) { + // Store the original post + $r = item_store($datarray2, false, false); + logger('remote-self post original item - Contact '.$contact['url'].' return '.$r.' Item '.print_r($datarray2, true), LOGGER_DEBUG); + } else + $datarray["app"] = "Feed"; + + return true; } function local_delivery($importer,$data) { $a = get_app(); - logger(__function__, LOGGER_TRACE); + logger(__function__, LOGGER_TRACE); if($importer['readonly']) { // We aren't receiving stuff from this person. But we will quietly ignore them @@ -2681,9 +2824,16 @@ function local_delivery($importer,$data) { if($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) { $name_updated = $elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']; $new_name = $elems['name'][0]['data']; + + // Manually checking for changed contact names + if (($new_name != $importer['name']) AND ($new_name != "") AND ($name_updated <= $importer['name-date'])) { + $name_updated = date("c"); + $photo_timestamp = date("c"); + } } if((x($elems,'link')) && ($elems['link'][0]['attribs']['']['rel'] === 'photo') && ($elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated'])) { - $photo_timestamp = datetime_convert('UTC','UTC',$elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']); + if ($photo_timestamp == "") + $photo_timestamp = datetime_convert('UTC','UTC',$elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']); $photo_url = $elems['link'][0]['attribs']['']['href']; } } @@ -2810,6 +2960,7 @@ function local_delivery($importer,$data) { thumb = '%s', micro = '%s', url = '%s', + nurl = '%s', request = '%s', confirm = '%s', notify = '%s', @@ -2821,6 +2972,7 @@ function local_delivery($importer,$data) { dbesc($newloc['thumb']), dbesc($newloc['micro']), dbesc($newloc['url']), + dbesc(normalise_link($newloc['url'])), dbesc($newloc['request']), dbesc($newloc['confirm']), dbesc($newloc['notify']), @@ -3714,27 +3866,7 @@ function local_delivery($importer,$data) { // This is my contact on another system, but it's really me. // Turn this into a wall post. - - if($importer['remote_self']) { - if ($importer['remote_self'] == 2) { - $r = q("SELECT `id`,`url`,`name`,`photo`,`network` FROM `contact` WHERE `uid` = %d AND `self`", - intval($importer['importer_uid'])); - if (count($r)) { - $datarray['contact-id'] = $r[0]["id"]; - - $datarray['owner-name'] = $r[0]["name"]; - $datarray['owner-link'] = $r[0]["url"]; - $datarray['owner-avatar'] = $r[0]["photo"]; - - $datarray['author-name'] = $datarray['owner-name']; - $datarray['author-link'] = $datarray['owner-link']; - $datarray['author-avatar'] = $datarray['owner-avatar']; - } - } - - $notify = true; - } else - $notify = false; + $notify = item_is_remote_self($importer, $datarray); $posted_id = item_store($datarray, false, $notify); @@ -4000,6 +4132,7 @@ 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)) @@ -4014,13 +4147,22 @@ function atom_entry($item,$type,$author,$owner,$comment = false,$cid = 0) { $o .= '' . "\r\n"; } + $htmlbody = $body; + + if ($item['title'] != "") + $htmlbody = "[b]".$item['title']."[/b]\n\n".$htmlbody; + + $htmlbody = bbcode(bb_remove_share_information($htmlbody), false, false, 7); + $o .= '' . xmlify($item['uri']) . '' . "\r\n"; $o .= '' . xmlify($item['title']) . '' . "\r\n"; $o .= '' . xmlify(datetime_convert('UTC','UTC',$item['created'] . '+00:00',ATOM_TIME)) . '' . "\r\n"; $o .= '' . xmlify(datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)) . '' . "\r\n"; $o .= '' . base64url_encode($body, true) . '' . "\r\n"; - $o .= '' . xmlify((($type === 'html') ? bbcode($body) : $body)) . '' . "\r\n"; + $o .= '' . xmlify((($type === 'html') ? $htmlbody : $body)) . '' . "\r\n"; $o .= '' . "\r\n"; + + if($comment) $o .= '' . intval($item['last-child']) . '' . "\r\n"; @@ -4438,7 +4580,7 @@ function drop_item($id,$interactive = true) { ); create_tags_from_item($item['id']); create_files_from_item($item['id']); - delete_thread($item['id']); + delete_thread($item['id'], $item['parent-uri']); // clean up categories and tags so they don't end up as orphans @@ -4532,8 +4674,8 @@ function drop_item($id,$interactive = true) { dbesc($item['parent-uri']), intval($item['uid']) ); - create_tags_from_item($item['parent-uri'], $item['uid']); - create_files_from_item($item['parent-uri'], $item['uid']); + create_tags_from_itemuri($item['parent-uri'], $item['uid']); + create_files_from_itemuri($item['parent-uri'], $item['uid']); delete_thread_uri($item['parent-uri'], $item['uid']); // ignore the result }