X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fostatus.php;h=a1da94f6a77fa915cafc613e147fb93e18fa1d54;hb=cb3077b7a9023a65b6dc13df065bfbbe7f7633fb;hp=e0b33a1a474839338927c95ed2bc3c228a2d03b9;hpb=0d2bf557de7e3b44d16cadf85dabf05546a4828e;p=friendica.git diff --git a/include/ostatus.php b/include/ostatus.php index e0b33a1a47..a1da94f6a7 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -3,20 +3,24 @@ * @file include/ostatus.php */ -require_once("include/Contact.php"); -require_once("include/threads.php"); -require_once("include/html2bbcode.php"); -require_once("include/bbcode.php"); -require_once("include/items.php"); -require_once("mod/share.php"); -require_once("include/enotify.php"); -require_once("include/socgraph.php"); -require_once("include/Photo.php"); -require_once("include/Scrape.php"); -require_once("include/follow.php"); -require_once("include/api.php"); -require_once("mod/proxy.php"); -require_once("include/xml.php"); +use Friendica\App; +use Friendica\Core\Config; +use Friendica\Network\Probe; + +require_once 'include/Contact.php'; +require_once 'include/threads.php'; +require_once 'include/html2bbcode.php'; +require_once 'include/bbcode.php'; +require_once 'include/items.php'; +require_once 'mod/share.php'; +require_once 'include/enotify.php'; +require_once 'include/socgraph.php'; +require_once 'include/Photo.php'; +require_once 'include/probe.php'; +require_once 'include/follow.php'; +require_once 'include/api.php'; +require_once 'mod/proxy.php'; +require_once 'include/xml.php'; /** * @brief This class contain functions for the OStatus protocol @@ -27,42 +31,6 @@ class ostatus { const OSTATUS_DEFAULT_POLL_TIMEFRAME = 1440; // given in minutes const OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS = 14400; // given in minutes - /** - * @brief Mix two paths together to possibly fix missing parts - * - * @param string $avatar Path to the avatar - * @param string $base Another path that is hopefully complete - * - * @return string fixed avatar path - */ - public static function fix_avatar($avatar, $base) { - $base_parts = parse_url($base); - - // Remove all parts that could create a problem - unset($base_parts['path']); - unset($base_parts['query']); - unset($base_parts['fragment']); - - $avatar_parts = parse_url($avatar); - - // Now we mix them - $parts = array_merge($base_parts, $avatar_parts); - - // And put them together again - $scheme = isset($parts['scheme']) ? $parts['scheme'] . '://' : ''; - $host = isset($parts['host']) ? $parts['host'] : ''; - $port = isset($parts['port']) ? ':' . $parts['port'] : ''; - $path = isset($parts['path']) ? $parts['path'] : ''; - $query = isset($parts['query']) ? '?' . $parts['query'] : ''; - $fragment = isset($parts['fragment']) ? '#' . $parts['fragment'] : ''; - - $fixed = $scheme.$host.$port.$path.$query.$fragment; - - logger('Base: '.$base.' - Avatar: '.$avatar.' - Fixed: '.$fixed, LOGGER_DATA); - - return $fixed; - } - /** * @brief Fetches author data * @@ -79,46 +47,72 @@ class ostatus { $author = array(); $author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue; $author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue; + $addr = $xpath->evaluate('atom:author/atom:email/text()', $context)->item(0)->nodeValue; $aliaslink = $author["author-link"]; $alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes; - if (is_object($alternate)) - foreach($alternate AS $attributes) - if ($attributes->name == "href") + if (is_object($alternate)) { + foreach ($alternate AS $attributes) { + if (($attributes->name == "href") AND ($attributes->textContent != "")) { $author["author-link"] = $attributes->textContent; + } + } + } - $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'", - intval($importer["uid"]), dbesc(normalise_link($author["author-link"])), - dbesc(normalise_link($aliaslink)), dbesc(NETWORK_STATUSNET)); - if ($r) { - $contact = $r[0]; - $author["contact-id"] = $r[0]["id"]; - } else - $author["contact-id"] = $contact["id"]; + $author["contact-id"] = $contact["id"]; + + if ($author["author-link"] != "") { + if ($aliaslink == "") { + $aliaslink = $author["author-link"]; + } + + $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'", + intval($importer["uid"]), dbesc(normalise_link($author["author-link"])), + dbesc(normalise_link($aliaslink)), dbesc(NETWORK_STATUSNET)); + + if (dbm::is_result($r)) { + $contact = $r[0]; + $author["contact-id"] = $r[0]["id"]; + $author["author-link"] = $r[0]["url"]; + } + } elseif ($addr != "") { + // Should not happen + $contact = dba::fetch_first("SELECT * FROM `contact` WHERE `uid` = ? AND `addr` = ? AND `network` != ?", + $importer["uid"], $addr, NETWORK_STATUSNET); + + if (dbm::is_result($contact)) { + $author["contact-id"] = $contact["id"]; + $author["author-link"] = $contact["url"]; + } + } $avatarlist = array(); $avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context); - foreach($avatars AS $avatar) { + foreach ($avatars AS $avatar) { $href = ""; $width = 0; - foreach($avatar->attributes AS $attributes) { - if ($attributes->name == "href") + foreach ($avatar->attributes AS $attributes) { + if ($attributes->name == "href") { $href = $attributes->textContent; - if ($attributes->name == "width") + } + if ($attributes->name == "width") { $width = $attributes->textContent; + } } - if (($width > 0) AND ($href != "")) + if (($width > 0) AND ($href != "")) { $avatarlist[$width] = $href; + } } if (count($avatarlist) > 0) { krsort($avatarlist); - $author["author-avatar"] = self::fix_avatar(current($avatarlist), $author["author-link"]); + $author["author-avatar"] = Probe::fixAvatar(current($avatarlist), $author["author-link"]); } $displayname = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue; - if ($displayname != "") + if ($displayname != "") { $author["author-name"] = $displayname; + } $author["owner-name"] = $author["author-name"]; $author["owner-link"] = $author["author-link"]; @@ -312,8 +306,10 @@ class ostatus { if ($first_child == "feed") { $entries = $xpath->query('/atom:feed/atom:entry'); + $header["protocol"] = PROTOCOL_OSTATUS_FEED; } else { $entries = $xpath->query('/atom:entry'); + $header["protocol"] = PROTOCOL_OSTATUS_SALMON; } $conversation = ""; $conversationlist = array(); @@ -370,7 +366,7 @@ class ostatus { } elseif ($item["object-type"] == ACTIVITY_OBJ_QUESTION) { $item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue; } - $item["object"] = $xml; + $item["source"] = $xml; /// @TODO /// Delete a message @@ -418,6 +414,19 @@ class ostatus { $item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue; $item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue; $conversation = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue; + $item['conversation-uri'] = $conversation; + + $conv = $xpath->query('ostatus:conversation', $entry); + if (is_object($conv->item(0))) { + foreach ($conv->item(0)->attributes AS $attributes) { + if ($attributes->name == "ref") { + $item['conversation-uri'] = $attributes->textContent; + } + if ($attributes->name == "href") { + $item['conversation-href'] = $attributes->textContent; + } + } + } $related = ""; @@ -443,7 +452,7 @@ class ostatus { foreach ($category->attributes AS $attributes) { if ($attributes->name == "term") { $term = $attributes->textContent; - if(strlen($item["tag"])) { + if (strlen($item["tag"])) { $item["tag"] .= ','; } $item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]"; @@ -471,6 +480,10 @@ class ostatus { break; case "ostatus:conversation": $conversation = $attribute['href']; + $item['conversation-href'] = $conversation; + if (!isset($item['conversation-uri'])) { + $item['conversation-uri'] = $item['conversation-href']; + } break; case "enclosure": $enclosure = $attribute['href']; @@ -720,11 +733,11 @@ class ostatus { $conversations = q("SELECT `term`.`oid`, `term`.`url`, `term`.`uid` FROM `term` STRAIGHT_JOIN `thread` ON `thread`.`iid` = `term`.`oid` AND `thread`.`uid` = `term`.`uid` WHERE `term`.`type` = 7 AND `term`.`term` > '%s' AND `thread`.`mention` - GROUP BY `term`.`url`, `term`.`uid` ORDER BY `term`.`term` DESC", dbesc($start)); + GROUP BY `term`.`url`, `term`.`uid`, `term`.`oid`, `term`.`term` ORDER BY `term`.`term` DESC", dbesc($start)); } else { $conversations = q("SELECT `oid`, `url`, `uid` FROM `term` WHERE `type` = 7 AND `term` > '%s' - GROUP BY `url`, `uid` ORDER BY `term` DESC", dbesc($start)); + GROUP BY `url`, `uid`, `oid`, `term` ORDER BY `term` DESC", dbesc($start)); } foreach ($conversations AS $conversation) { @@ -897,6 +910,8 @@ class ostatus { ($item["verb"] == ACTIVITY_LIKE) OR ($conversation_url == "")) { $item_stored = item_store($item, $all_threads); return $item_stored; + } elseif (count($item) > 0) { + $item = store_conversation($item); } // Get the parent @@ -1137,6 +1152,7 @@ class ostatus { continue; } + /// @TODO One statment is okay (until if () ) $arr = array(); $arr["network"] = $details["network"]; $arr["uri"] = $single_conv->id; @@ -1153,13 +1169,17 @@ class ostatus { $arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName; $arr["owner-link"] = $actor; - $arr["owner-avatar"] = self::fix_avatar($single_conv->actor->image->url, $arr["owner-link"]); + $arr["owner-avatar"] = Probe::fixAvatar($single_conv->actor->image->url, $arr["owner-link"]); $arr["author-name"] = $arr["owner-name"]; $arr["author-link"] = $arr["owner-link"]; $arr["author-avatar"] = $arr["owner-avatar"]; $arr["body"] = add_page_info_to_body(html2bbcode($single_conv->content)); + if (isset($single_conv->status_net->conversation)) { + $arr['conversation-uri'] = $single_conv->status_net->conversation; + } + if (isset($single_conv->status_net->notice_info->source)) $arr["app"] = strip_tags($single_conv->status_net->notice_info->source); elseif (isset($single_conv->statusnet->notice_info->source)) @@ -1172,7 +1192,9 @@ class ostatus { $arr["app"] = "OStatus"; - $arr["object"] = json_encode($single_conv); + $arr["source"] = json_encode($single_conv); + $arr["protocol"] = PROTOCOL_GS_CONVERSATION; + $arr["verb"] = $parent["verb"]; $arr["visible"] = $parent["visible"]; $arr["location"] = $single_conv->location->displayName; @@ -1212,7 +1234,7 @@ class ostatus { $arr["author-name"] = $single_conv->object->actor->contact->displayName; } $arr["author-link"] = $single_conv->object->actor->url; - $arr["author-avatar"] = self::fix_avatar($single_conv->object->actor->image->url, $arr["author-link"]); + $arr["author-avatar"] = Probe::fixAvatar($single_conv->object->actor->image->url, $arr["author-link"]); $arr["app"] = $single_conv->object->provider->displayName."#"; //$arr["verb"] = $single_conv->object->verb; @@ -1404,6 +1426,7 @@ class ostatus { $root->setAttribute("xmlns:poco", NAMESPACE_POCO); $root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS); $root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET); + $root->setAttribute("xmlns:mastodon", NAMESPACE_MASTODON); $attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION); xml::add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes); @@ -1479,15 +1502,7 @@ class ostatus { $o = ""; $siteinfo = get_attached_data($item["body"]); - switch($siteinfo["type"]) { - case 'link': - $attributes = array("rel" => "enclosure", - "href" => $siteinfo["url"], - "type" => "text/html; charset=UTF-8", - "length" => "", - "title" => $siteinfo["title"]); - xml::add_element($doc, $root, "link", "", $attributes); - break; + switch ($siteinfo["type"]) { case 'photo': $imgdata = get_photo_info($siteinfo["image"]); $attributes = array("rel" => "enclosure", @@ -1509,29 +1524,31 @@ class ostatus { } if (($siteinfo["type"] != "photo") AND isset($siteinfo["image"])) { - $photodata = get_photo_info($siteinfo["image"]); + $imgdata = get_photo_info($siteinfo["image"]); + $attributes = array("rel" => "enclosure", + "href" => $siteinfo["image"], + "type" => $imgdata["mime"], + "length" => intval($imgdata["size"])); - $attributes = array("rel" => "preview", "href" => $siteinfo["image"], "media:width" => $photodata[0], "media:height" => $photodata[1]); xml::add_element($doc, $root, "link", "", $attributes); } - - $arr = explode('[/attach],',$item['attach']); - if(count($arr)) { - foreach($arr as $r) { + $arr = explode('[/attach],', $item['attach']); + if (count($arr)) { + foreach ($arr as $r) { $matches = false; - $cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches); - if($cnt) { + $cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|', $r, $matches); + if ($cnt) { $attributes = array("rel" => "enclosure", "href" => $matches[1], "type" => $matches[3]); - if(intval($matches[2])) + if (intval($matches[2])) { $attributes["length"] = intval($matches[2]); - - if(trim($matches[4]) != "") + } + if (trim($matches[4]) != "") { $attributes["title"] = trim($matches[4]); - + } xml::add_element($doc, $root, "link", "", $attributes); } } @@ -1548,14 +1565,16 @@ class ostatus { */ private function add_author($doc, $owner) { - $r = q("SELECT `homepage` FROM `profile` WHERE `uid` = %d AND `is-default` LIMIT 1", intval($owner["uid"])); + $r = q("SELECT `homepage`, `publish` FROM `profile` WHERE `uid` = %d AND `is-default` LIMIT 1", intval($owner["uid"])); if ($r) $profile = $r[0]; $author = $doc->createElement("author"); + xml::add_element($doc, $author, "id", $owner["url"]); xml::add_element($doc, $author, "activity:object-type", ACTIVITY_OBJ_PERSON); xml::add_element($doc, $author, "uri", $owner["url"]); - xml::add_element($doc, $author, "name", $owner["name"]); + xml::add_element($doc, $author, "name", $owner["nick"]); + xml::add_element($doc, $author, "email", $owner["addr"]); xml::add_element($doc, $author, "summary", bbcode($owner["about"], false, false, 7)); $attributes = array("rel" => "alternate", "type" => "text/html", "href" => $owner["url"]); @@ -1602,6 +1621,9 @@ class ostatus { xml::add_element($doc, $author, "statusnet:profile_info", "", array("local_id" => $owner["uid"])); } + if ($profile["publish"]) { + xml::add_element($doc, $author, "mastodon:scope", "public"); + } return $author; } @@ -1775,7 +1797,7 @@ class ostatus { self::entry_content($doc, $as_object, $repeated_item, $owner, "", "", false); $author = self::add_author($doc, $contact); - $as_object->appendChild($author); + $as_object->appendChild($author); $as_object2 = $doc->createElement("activity:object"); @@ -1997,6 +2019,7 @@ class ostatus { $entry->setAttribute("xmlns:poco", NAMESPACE_POCO); $entry->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS); $entry->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET); + $entry->setAttribute("xmlns:mastodon", NAMESPACE_MASTODON); $author = self::add_author($doc, $owner); $entry->appendChild($author); @@ -2063,33 +2086,54 @@ class ostatus { $parent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `id` = %d", intval($item["parent"])); $parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']); + $thrparent = q("SELECT `guid`, `author-link`, `owner-link`, `plink` FROM `item` WHERE `uid` = %d AND `uri` = '%s'", + intval($owner["uid"]), + dbesc($parent_item)); + if ($thrparent) { + $mentioned[$thrparent[0]["author-link"]] = $thrparent[0]["author-link"]; + $mentioned[$thrparent[0]["owner-link"]] = $thrparent[0]["owner-link"]; + $parent_plink = $thrparent[0]["plink"]; + } else { + $mentioned[$parent[0]["author-link"]] = $parent[0]["author-link"]; + $mentioned[$parent[0]["owner-link"]] = $parent[0]["owner-link"]; + $parent_plink = App::get_baseurl()."/display/".$parent[0]["guid"]; + } + $attributes = array( "ref" => $parent_item, - "type" => "text/html", - "href" => App::get_baseurl()."/display/".$parent[0]["guid"]); + "href" => $parent_plink); xml::add_element($doc, $entry, "thr:in-reply-to", "", $attributes); $attributes = array( "rel" => "related", - "href" => App::get_baseurl()."/display/".$parent[0]["guid"]); + "href" => $parent_plink); xml::add_element($doc, $entry, "link", "", $attributes); + } - $mentioned[$parent[0]["author-link"]] = $parent[0]["author-link"]; - $mentioned[$parent[0]["owner-link"]] = $parent[0]["owner-link"]; + if (intval($item["parent"]) > 0) { + $conversation_href = App::get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]; + $conversation_uri = $conversation_href; - $thrparent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `uid` = %d AND `uri` = '%s'", - intval($owner["uid"]), - dbesc($parent_item)); - if ($thrparent) { - $mentioned[$thrparent[0]["author-link"]] = $thrparent[0]["author-link"]; - $mentioned[$thrparent[0]["owner-link"]] = $thrparent[0]["owner-link"]; + if (isset($parent_item)) { + $r = dba::fetch_first("SELECT `conversation-uri`, `conversation-href` FROM `conversation` WHERE `item-uri` = ?", $parent_item); + if (dbm::is_result($r)) { + if ($r['conversation-uri'] != '') { + $conversation_uri = $r['conversation-uri']; + } + if ($r['conversation-href'] != '') { + $conversation_href = $r['conversation-href']; + } + } } - } - if (intval($item["parent"]) > 0) { - $conversation = App::get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]; - xml::add_element($doc, $entry, "link", "", array("rel" => "ostatus:conversation", "href" => $conversation)); - xml::add_element($doc, $entry, "ostatus:conversation", $conversation); + xml::add_element($doc, $entry, "link", "", array("rel" => "ostatus:conversation", "href" => $conversation_href)); + + $attributes = array( + "href" => $conversation_href, + "local_id" => $item["parent"], + "ref" => $conversation_uri); + + xml::add_element($doc, $entry, "ostatus:conversation", $conversation_uri, $attributes); } $tags = item_getfeedtags($item); @@ -2127,6 +2171,7 @@ class ostatus { xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned", "ostatus:object-type" => "http://activitystrea.ms/schema/1.0/collection", "href" => "http://activityschema.org/collection/public")); + xml::add_element($doc, $entry, "mastodon:scope", "public"); } if(count($tags)) @@ -2156,7 +2201,7 @@ class ostatus { /** * @brief Creates the XML feed for a given nickname * - * @param app $a The application class + * @param App $a The application class * @param string $owner_nick Nickname of the feed owner * @param string $last_update Date of the last update * @@ -2173,7 +2218,7 @@ class ostatus { $owner = $r[0]; - if(!strlen($last_update)) + if (!strlen($last_update)) $last_update = 'now -30 days'; $check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s'); @@ -2218,6 +2263,9 @@ class ostatus { $root = self::add_header($doc, $owner); foreach ($items AS $item) { + if (Config::get('system', 'ostatus_debug')) { + $item['body'] .= '🍼'; + } $entry = self::entry($doc, $item, $owner); $root->appendChild($entry); } @@ -2238,6 +2286,10 @@ class ostatus { $doc = new DOMDocument('1.0', 'utf-8'); $doc->formatOutput = true; + if (Config::get('system', 'ostatus_debug')) { + $item['body'] .= '🐟'; + } + $entry = self::entry($doc, $item, $owner, true); $doc->appendChild($entry); @@ -2245,4 +2297,3 @@ class ostatus { return(trim($doc->saveXML())); } } -?>