Merge remote-tracking branch 'upstream/develop' into dfrn-reshare

This commit is contained in:
Michael 2018-04-18 03:12:13 +00:00
commit 88353ce56f
291 changed files with 98692 additions and 89038 deletions

View file

@ -11,6 +11,7 @@ namespace Friendica\Protocol;
use Friendica\App;
use Friendica\Content\OEmbed;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\L10n;
@ -18,11 +19,11 @@ use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\Event;
use Friendica\Model\GContact;
use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Model\Term;
use Friendica\Model\User;
use Friendica\Object\Image;
use Friendica\Protocol\OStatus;
@ -30,6 +31,7 @@ use Friendica\Util\Crypto;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\XML;
use Friendica\Protocol\Diaspora;
use dba;
use DOMDocument;
use DOMXPath;
@ -40,9 +42,7 @@ require_once 'boot.php';
require_once 'include/dba.php';
require_once "include/enotify.php";
require_once "include/items.php";
require_once "include/event.php";
require_once "include/text.php";
require_once "include/html2bbcode.php";
/**
* @brief This class contain functions to create and send DFRN XML files
@ -1146,13 +1146,20 @@ class DFRN
* @param string $atom Content that will be transmitted
* @param bool $dissolve (to be documented)
*
* @return int Deliver status. -1 means an error.
* @return int Deliver status. Negative values mean an error.
* @todo Add array type-hint for $owner, $contact
*/
public static function deliver($owner, $contact, $atom, $dissolve = false)
{
$a = get_app();
// At first try the Diaspora transport layer
$ret = self::transmit($owner, $contact, $atom);
if ($ret >= 200) {
logger('Delivery via Diaspora transport layer was successful with status ' . $ret);
return $ret;
}
$idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']);
if ($contact['duplex'] && $contact['dfrn-id']) {
@ -1196,13 +1203,13 @@ class DFRN
$xml = $ret['body'];
$curl_stat = $a->get_curl_code();
if (!$curl_stat) {
if (empty($curl_stat)) {
return -3; // timed out
}
logger('dfrn_deliver: ' . $xml, LOGGER_DATA);
if (! $xml) {
if (empty($xml)) {
return 3;
}
@ -1215,7 +1222,7 @@ class DFRN
$res = XML::parseString($xml);
if ((intval($res->status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) {
return (($res->status) ? $res->status : 3);
return ($res->status ? $res->status : 3);
}
$postvars = [];
@ -1338,11 +1345,11 @@ class DFRN
logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA);
$curl_stat = $a->get_curl_code();
if ((!$curl_stat) || (!strlen($xml))) {
if (empty($curl_stat) || empty($xml)) {
return -9; // timed out
}
if (($curl_stat == 503) && (stristr($a->get_curl_headers(), 'retry-after'))) {
if (($curl_stat == 503) && stristr($a->get_curl_headers(), 'retry-after')) {
return -10;
}
@ -1358,6 +1365,11 @@ class DFRN
return -11;
}
// Possibly old servers had returned an empty value when everything was okay
if (empty($res->status)) {
$res->status = 200;
}
if (!empty($res->message)) {
logger('Delivery returned status '.$res->status.' - '.$res->message, LOGGER_DEBUG);
}
@ -1369,6 +1381,79 @@ class DFRN
return intval($res->status);
}
/**
* @brief Transmits atom content to the contacts via the Diaspora transport layer
*
* @param array $owner Owner record
* @param array $contact Contact record of the receiver
* @param string $atom Content that will be transmitted
*
* @return int Deliver status. Negative values mean an error.
*/
public static function transmit($owner, $contact, $atom, $public_batch = false)
{
$a = get_app();
if (empty($contact['addr'])) {
logger('Empty contact handle for ' . $contact['id'] . ' - ' . $contact['url'] . ' - trying to update it.');
if (Contact::updateFromProbe($contact['id'])) {
$new_contact = dba::selectFirst('contact', ['addr'], ['id' => $contact['id']]);
$contact['addr'] = $new_contact['addr'];
}
if (empty($contact['addr'])) {
logger('Unable to find contact handle for ' . $contact['id'] . ' - ' . $contact['url']);
return -21;
}
}
$fcontact = Diaspora::personByHandle($contact['addr']);
if (empty($fcontact)) {
logger('Unable to find contact details for ' . $contact['id'] . ' - ' . $contact['addr']);
return -22;
}
$envelope = Diaspora::buildMessage($atom, $owner, $contact, $owner['uprvkey'], $fcontact['pubkey'], $public_batch);
$dest_url = ($public_batch ? $fcontact["batch"] : $contact["notify"]);
$content_type = ($public_batch ? "application/magic-envelope+xml" : "application/json");
$xml = Network::post($dest_url, $envelope, ["Content-Type: ".$content_type]);
$curl_stat = $a->get_curl_code();
if (empty($curl_stat) || empty($xml)) {
logger('Empty answer from ' . $contact['id'] . ' - ' . $dest_url);
return -9; // timed out
}
if (($curl_stat == 503) && (stristr($a->get_curl_headers(), 'retry-after'))) {
return -10;
}
if (strpos($xml, '<?xml') === false) {
logger('No valid XML returned from ' . $contact['id'] . ' - ' . $dest_url);
logger('Returned XML: ' . $xml, LOGGER_DATA);
return 3;
}
$res = XML::parseString($xml);
if (empty($res->status)) {
return -23;
}
if (!empty($res->message)) {
logger('Transmit to ' . $dest_url . ' returned status '.$res->status.' - '.$res->message, LOGGER_DEBUG);
}
if ($res->status == 200) {
Contact::unmarkForArchival($contact);
}
return intval($res->status);
}
/**
* @brief Add new birthday event for this person
*
@ -1434,7 +1519,7 @@ class DFRN
$contact_old = dba::fetch_first("SELECT `id`, `uid`, `url`, `network`, `avatar-date`, `avatar`, `name-date`, `uri-date`, `addr`,
`name`, `nick`, `about`, `location`, `keywords`, `xmpp`, `bdyear`, `bd`, `hidden`, `contact-type`
FROM `contact` WHERE `uid` = ? AND `nurl` = ? AND `network` != ?",
$importer["uid"],
$importer["importer_uid"],
normalise_link($author["link"]),
NETWORK_STATUSNET
);
@ -1444,7 +1529,7 @@ class DFRN
$author["network"] = $contact_old["network"];
} else {
if (!$onlyfetch) {
logger("Contact ".$author["link"]." wasn't found for user ".$importer["uid"]." XML: ".$xml, LOGGER_DEBUG);
logger("Contact ".$author["link"]." wasn't found for user ".$importer["importer_uid"]." XML: ".$xml, LOGGER_DEBUG);
}
$author["contact-id"] = $importer["id"];
@ -1640,7 +1725,7 @@ class DFRN
Contact::updateAvatar(
$author['avatar'],
$importer['uid'],
$importer['importer_uid'],
$contact['id'],
(strtotime($contact['avatar-date']) > strtotime($contact_old['avatar-date']) || ($author['avatar'] != $contact_old['avatar']))
);
@ -1658,7 +1743,7 @@ class DFRN
$poco["contact-type"] = $contact["contact-type"];
$gcid = GContact::update($poco);
GContact::link($gcid, $importer["uid"], $contact["id"]);
GContact::link($gcid, $importer["importer_uid"], $contact["id"]);
}
return $author;
@ -2079,8 +2164,8 @@ class DFRN
return false;
}
$fields = ['title' => $item["title"], 'body' => $item["body"],
'tag' => $item["tag"], 'changed' => DateTimeFormat::utcNow(),
$fields = ['title' => defaults($item, 'title', ''), 'body' => defaults($item, 'body', ''),
'tag' => defaults($item, 'tag', ''), 'changed' => DateTimeFormat::utcNow(),
'edited' => DateTimeFormat::utc($item["edited"])];
$condition = ["`uri` = ? AND `uid` IN (0, ?)", $item["uri"], $importer["importer_uid"]];
@ -2454,7 +2539,7 @@ class DFRN
$purifier = new HTMLPurifier($config);
$item['body'] = $purifier->purify($item['body']);
$item['body'] = @html2bbcode($item['body']);
$item['body'] = @HTML::toBBCode($item['body']);
}
/// @todo We should check for a repeated post and if we know the repeated author.
@ -2614,11 +2699,11 @@ class DFRN
// Is it an event?
if ($item["object-type"] == ACTIVITY_OBJ_EVENT) {
logger("Item ".$item["uri"]." seems to contain an event.", LOGGER_DEBUG);
$ev = bbtoevent($item["body"]);
$ev = Event::fromBBCode($item["body"]);
if ((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) {
logger("Event in item ".$item["uri"]." was found.", LOGGER_DEBUG);
$ev["cid"] = $importer["id"];
$ev["uid"] = $importer["uid"];
$ev["uid"] = $importer["importer_uid"];
$ev["uri"] = $item["uri"];
$ev["edited"] = $item["edited"];
$ev["private"] = $item["private"];
@ -2627,13 +2712,13 @@ class DFRN
$r = q(
"SELECT `id` FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
dbesc($item["uri"]),
intval($importer["uid"])
intval($importer["importer_uid"])
);
if (DBM::is_result($r)) {
$ev["id"] = $r[0]["id"];
}
$event_id = event_store($ev);
$event_id = Event::store($ev);
logger("Event ".$event_id." was stored", LOGGER_DEBUG);
return;
}
@ -2682,6 +2767,14 @@ class DFRN
return true;
}
} else { // $entrytype == DFRN_TOP_LEVEL
if ($importer["readonly"]) {
logger('ignoring read-only contact '.$importer["id"]);
return;
}
if ($importer["uid"] == 0) {
logger("Contact ".$importer["id"]." isn't known to user ".$importer["importer_uid"].". The post will be ignored.", LOGGER_DEBUG);
return;
}
if (!link_compare($item["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,
@ -2737,10 +2830,10 @@ class DFRN
return false;
}
$condition = ["`uri` = ? AND `uid` = ? AND NOT `file` LIKE '%[%'", $uri, $importer["uid"]];
$condition = ["`uri` = ? AND `uid` = ? AND NOT `file` LIKE '%[%'", $uri, $importer["importer_uid"]];
$item = dba::selectFirst('item', ['id', 'parent', 'contact-id'], $condition);
if (!DBM::is_result($item)) {
logger("Item with uri " . $uri . " for user " . $importer["uid"] . " wasn't found.", LOGGER_DEBUG);
logger("Item with uri " . $uri . " for user " . $importer["importer_uid"] . " wasn't found.", LOGGER_DEBUG);
return;
}
@ -2809,7 +2902,7 @@ class DFRN
$xpath->registerNamespace("statusnet", NAMESPACE_STATUSNET);
$header = [];
$header["uid"] = $importer["uid"];
$header["uid"] = $importer["importer_uid"];
$header["network"] = NETWORK_DFRN;
$header["type"] = "remote";
$header["wall"] = 0;
@ -2828,7 +2921,7 @@ class DFRN
self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", false, $xml);
}
logger("Import DFRN message for user " . $importer["uid"] . " from contact " . $importer["id"], LOGGER_DEBUG);
logger("Import DFRN message for user " . $importer["importer_uid"] . " from contact " . $importer["id"], LOGGER_DEBUG);
// The account type is new since 3.5.1
if ($xpath->query("/atom:feed/dfrn:account_type")->length > 0) {
@ -2854,21 +2947,16 @@ class DFRN
self::processRelocation($xpath, $relocation, $importer);
}
if ($importer["readonly"]) {
// We aren't receiving stuff from this person. But we will quietly ignore them
// rather than a blatant "go away" message.
logger('ignoring contact '.$importer["id"]);
return 403;
}
if (($importer["uid"] != 0) && !$importer["readonly"]) {
$mails = $xpath->query("/atom:feed/dfrn:mail");
foreach ($mails as $mail) {
self::processMail($xpath, $mail, $importer);
}
$mails = $xpath->query("/atom:feed/dfrn:mail");
foreach ($mails as $mail) {
self::processMail($xpath, $mail, $importer);
}
$suggestions = $xpath->query("/atom:feed/dfrn:suggest");
foreach ($suggestions as $suggestion) {
self::processSuggestion($xpath, $suggestion, $importer);
$suggestions = $xpath->query("/atom:feed/dfrn:suggest");
foreach ($suggestions as $suggestion) {
self::processSuggestion($xpath, $suggestion, $importer);
}
}
$deletions = $xpath->query("/atom:feed/at:deleted-entry");
@ -2896,7 +2984,7 @@ class DFRN
self::processEntry($header, $xpath, $entry, $importer, $xml);
}
}
logger("Import done for user " . $importer["uid"] . " from contact " . $importer["id"], LOGGER_DEBUG);
logger("Import done for user " . $importer["importer_uid"] . " from contact " . $importer["id"], LOGGER_DEBUG);
return 200;
}

View file

@ -31,6 +31,7 @@ use Friendica\Util\Crypto;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\XML;
use Friendica\Util\Map;
use dba;
use SimpleXMLElement;
@ -46,60 +47,140 @@ class Diaspora
/**
* @brief Return a list of relay servers
*
* This is an experimental Diaspora feature.
* The list contains not only the official relays but also servers that we serve directly
*
* @param integer $item_id The id of the item that is sent
* @param array $contacts The previously fetched contacts
*
* @return array of relay servers
*/
public static function relayList()
public static function relayList($item_id, $contacts = [])
{
$serverlist = [];
// Fetching relay servers
$serverdata = Config::get("system", "relay_server");
if ($serverdata == "") {
return [];
}
$relay = [];
$servers = explode(",", $serverdata);
foreach ($servers as $server) {
$server = trim($server);
$addr = "relay@".str_replace("http://", "", normalise_link($server));
$batch = $server."/receive/public";
$relais = q(
"SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' AND `addr` = '%s' AND `nurl` = '%s' LIMIT 1",
dbesc($batch),
dbesc($addr),
dbesc(normalise_link($server))
);
if (!$relais) {
$r = q(
"INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`)
VALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')",
DateTimeFormat::utcNow(),
dbesc($addr),
dbesc($addr),
dbesc($server),
dbesc(normalise_link($server)),
dbesc($batch),
dbesc(NETWORK_DIASPORA),
intval(CONTACT_IS_FOLLOWER),
dbesc(DateTimeFormat::utcNow()),
dbesc(DateTimeFormat::utcNow()),
dbesc(DateTimeFormat::utcNow())
);
$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
if ($relais) {
$relay[] = $relais[0];
}
} else {
$relay[] = $relais[0];
if ($serverdata != "") {
$servers = explode(",", $serverdata);
foreach ($servers as $server) {
$serverlist[$server] = trim($server);
}
}
return $relay;
if (Config::get("system", "relay_directly", false)) {
// Servers that want to get all content
$servers = dba::select('gserver', ['url'], ['relay-subscribe' => true, 'relay-scope' => 'all']);
while ($server = dba::fetch($servers)) {
$serverlist[$server['url']] = $server['url'];
}
// All tags of the current post
$condition = ['otype' => TERM_OBJ_POST, 'type' => TERM_HASHTAG, 'oid' => $item_id];
$tags = dba::select('term', ['term'], $condition);
$taglist = [];
while ($tag = dba::fetch($tags)) {
$taglist[] = $tag['term'];
}
// All servers who wants content with this tag
$tagserverlist = [];
if (!empty($taglist)) {
$tagserver = dba::select('gserver-tag', ['gserver-id'], ['tag' => $taglist]);
while ($server = dba::fetch($tagserver)) {
$tagserverlist[] = $server['gserver-id'];
}
}
// All adresses with the given id
if (!empty($tagserverlist)) {
$servers = dba::select('gserver', ['url'], ['relay-subscribe' => true, 'relay-scope' => 'tags', 'id' => $tagserverlist]);
while ($server = dba::fetch($servers)) {
$serverlist[$server['url']] = $server['url'];
}
}
}
// Now we are collecting all relay contacts
foreach ($serverlist as $server_url) {
// We don't send messages to ourselves
if (link_compare($server_url, System::baseUrl())) {
continue;
}
$contact = self::getRelayContact($server_url);
if (is_bool($contact)) {
continue;
}
$exists = false;
foreach ($contacts as $entry) {
if ($entry['batch'] == $contact['batch']) {
$exists = true;
}
}
if (!$exists) {
$contacts[] = $contact;
}
}
return $contacts;
}
/**
* @brief Return a contact for a given server address or creates a dummy entry
*
* @param string $server_url The url of the server
* @return array with the contact
*/
private static function getRelayContact($server_url)
{
$batch = $server_url . '/receive/public';
$fields = ['batch', 'id', 'name', 'network', 'archive', 'blocked'];
// Fetch the relay contact
$condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch,
'contact-type' => ACCOUNT_TYPE_RELAY];
$contact = dba::selectFirst('contact', $fields, $condition);
// If there is nothing found, we check if there is some unmarked relay
// This code segment can be removed before the release 2018-05
if (!DBM::is_result($contact)) {
$condition = ['uid' => 0, 'network' => NETWORK_DIASPORA, 'batch' => $batch,
'name' => 'relay', 'nick' => 'relay', 'url' => $server_url];
$contact = dba::selectFirst('contact', $fields, $condition);
if (DBM::is_result($contact)) {
// Mark the relay account as a relay account
$fields = ['contact-type' => ACCOUNT_TYPE_RELAY];
dba::update('contact', $fields, ['id' => $contact['id']]);
}
}
if (DBM::is_result($contact)) {
if ($contact['archive'] || $contact['blocked']) {
return false;
}
return $contact;
} else {
$fields = ['uid' => 0, 'created' => DateTimeFormat::utcNow(),
'name' => 'relay', 'nick' => 'relay',
'url' => $server_url, 'nurl' => normalise_link($server_url),
'batch' => $batch, 'network' => NETWORK_DIASPORA,
'rel' => CONTACT_IS_FOLLOWER, 'blocked' => false,
'contact-type' => ACCOUNT_TYPE_RELAY,
'pending' => false, 'writable' => true];
dba::insert('contact', $fields);
$fields = ['batch', 'id', 'name', 'network'];
$contact = dba::selectFirst('contact', $fields, $condition);
if (DBM::is_result($contact)) {
return $contact;
}
}
// It should never happen that we arrive here
return [];
}
/**
@ -222,11 +303,20 @@ class Diaspora
$signable_data = $msg.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
if ($handle == '') {
logger('No author could be decoded. Discarding. Message: ' . $envelope);
return false;
}
$key = self::key($handle);
if ($key == '') {
logger("Couldn't get a key for handle " . $handle . ". Discarding.");
return false;
}
$verify = Crypto::rsaVerify($signable_data, $sig, $key);
if (!$verify) {
logger('Message did not verify. Discarding.');
logger('Message from ' . $handle . ' did not verify. Discarding.');
return false;
}
@ -322,7 +412,16 @@ class Diaspora
// Get the senders' public key
$key_id = $base->sig[0]->attributes()->key_id[0];
$author_addr = base64_decode($key_id);
if ($author_addr == '') {
logger('No author could be decoded. Discarding. Message: ' . $xml);
System::httpExit(400);
}
$key = self::key($author_addr);
if ($key == '') {
logger("Couldn't get a key for handle " . $author_addr . ". Discarding.");
System::httpExit(400);
}
$verify = Crypto::rsaVerify($signed_data, $signature, $key);
if (!$verify) {
@ -2212,7 +2311,10 @@ class Diaspora
}
logger('Received participation for ID: '.$item['id'].' - Contact: '.$contact_id.' - Server: '.$server, LOGGER_DEBUG);
dba::insert('participation', ['iid' => $item['id'], 'cid' => $contact_id, 'fid' => $person['id'], 'server' => $server]);
if (!dba::exists('participation', ['iid' => $item['id'], 'server' => $server])) {
dba::insert('participation', ['iid' => $item['id'], 'cid' => $contact_id, 'fid' => $person['id'], 'server' => $server]);
}
// Send all existing comments and likes to the requesting server
$comments = dba::p("SELECT `item`.`id`, `item`.`verb`, `contact`.`self`
@ -3143,7 +3245,7 @@ class Diaspora
*
* @return string The message that will be transmitted to other servers
*/
private static function buildMessage($msg, $user, $contact, $prvkey, $pubkey, $public = false)
public static function buildMessage($msg, $user, $contact, $prvkey, $pubkey, $public = false)
{
// The message is put into an envelope with the sender's signature
$envelope = self::buildMagicEnvelope($msg, $user);
@ -3197,13 +3299,16 @@ class Diaspora
}
$logid = random_string(4);
$dest_url = ($public_batch ? $contact["batch"] : $contact["notify"]);
// Fetch the fcontact entry when there is missing data
// Will possibly happen when data is transmitted to a DFRN contact
if (empty($dest_url) && !empty($contact['addr'])) {
// We always try to use the data from the fcontact table.
// This is important for transmitting data to Friendica servers.
if (!empty($contact['addr'])) {
$fcontact = self::personByHandle($contact['addr']);
$dest_url = ($public_batch ? $fcontact["batch"] : $fcontact["notify"]);
if (!empty($fcontact)) {
$dest_url = ($public_batch ? $fcontact["batch"] : $fcontact["notify"]);
}
}
if (!$dest_url) {
@ -3227,10 +3332,10 @@ class Diaspora
}
}
logger("transmit: ".$logid."-".$guid." returns: ".$return_code);
logger("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code);
if (!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) {
if (!$no_queue) {
if (!$no_queue && ($contact['contact-type'] != ACCOUNT_TYPE_RELAY)) {
logger("queue message");
// queue message for redelivery
Queue::add($contact["id"], NETWORK_DIASPORA, $envelope, $public_batch, $guid);
@ -3588,10 +3693,18 @@ class Diaspora
$eventdata['description'] = html_entity_decode(BBCode::toMarkdown($event['desc']));
}
if ($event['location']) {
$event['location'] = preg_replace("/\[map\](.*?)\[\/map\]/ism", '$1', $event['location']);
$coord = Map::getCoordinates($event['location']);
$location = [];
$location["address"] = html_entity_decode(BBCode::toMarkdown($event['location']));
$location["lat"] = 0;
$location["lng"] = 0;
if (!empty($coord['lat']) && !empty($coord['lon'])) {
$location["lat"] = $coord['lat'];
$location["lng"] = $coord['lon'];
} else {
$location["lat"] = 0;
$location["lng"] = 0;
}
$eventdata['location'] = $location;
}
@ -3638,6 +3751,12 @@ class Diaspora
$title = $item["title"];
$body = $item["body"];
if ($item['author-link'] != $item['owner-link']) {
require_once 'mod/share.php';
$body = share_header($item['author-name'], $item['author-link'], $item['author-avatar'],
"", $item['created'], $item['plink']) . $body . '[/share]';
}
// convert to markdown
$body = html_entity_decode(BBCode::toMarkdown($body));
@ -3685,7 +3804,13 @@ class Diaspora
if (count($event)) {
$message['event'] = $event;
/// @todo Once Diaspora supports it, we will remove the body
if (!empty($event['location']['address']) &&
!empty($event['location']['lat']) &&
!empty($event['location']['lng'])) {
$message['location'] = $event['location'];
}
/// @todo Once Diaspora supports it, we will remove the body and the location hack above
// $message['text'] = '';
}
}

View file

@ -4,7 +4,7 @@
*/
namespace Friendica\Protocol;
require_once 'include/html2plain.php';
use Friendica\Content\Text\HTML;
/**
* @brief Email class
@ -111,7 +111,7 @@ class Email
if (trim($ret['body']) == '') {
$ret['body'] = self::messageGetPart($mbox, $uid, $struc, 0, 'plain');
} else {
$ret['body'] = html2bbcode($ret['body']);
$ret['body'] = HTML::toBBCode($ret['body']);
}
} else {
$text = '';
@ -128,7 +128,7 @@ class Email
}
}
if (trim($html) != '') {
$ret['body'] = html2bbcode($html);
$ret['body'] = HTML::toBBCode($html);
} else {
$ret['body'] = $text;
}
@ -328,7 +328,7 @@ class Email
$body .= "Content-Transfer-Encoding: 8bit\n";
$body .= "Content-Type: text/plain; charset=utf-8; format=flowed\n\n";
$body .= html2plain($html)."\n";
$body .= HTML::toPlaintext($html)."\n";
$body .= "--=_".$part."\n";
$body .= "Content-Transfer-Encoding: 8bit\n";

View file

@ -10,12 +10,13 @@ use Friendica\Database\DBM;
use Friendica\Core\System;
use Friendica\Model\Item;
use Friendica\Util\Network;
use Friendica\Content\Text\HTML;
use dba;
use DOMDocument;
use DOMXPath;
require_once 'include/dba.php';
require_once 'include/html2bbcode.php';
require_once 'include/items.php';
/**
@ -85,9 +86,9 @@ class Feed {
if ($xpath->query('/atom:feed')->length > 0) {
$alternate = $xpath->query("atom:link[@rel='alternate']")->item(0)->attributes;
if (is_object($alternate)) {
foreach ($alternate AS $attributes) {
if ($attributes->name == "href") {
$author["author-link"] = $attributes->textContent;
foreach ($alternate AS $attribute) {
if ($attribute->name == "href") {
$author["author-link"] = $attribute->textContent;
}
}
}
@ -98,9 +99,9 @@ class Feed {
if ($author["author-link"] == "") {
$self = $xpath->query("atom:link[@rel='self']")->item(0)->attributes;
if (is_object($self)) {
foreach ($self AS $attributes) {
if ($attributes->name == "href") {
$author["author-link"] = $attributes->textContent;
foreach ($self AS $attribute) {
if ($attribute->name == "href") {
$author["author-link"] = $attribute->textContent;
}
}
}
@ -140,9 +141,9 @@ class Feed {
}
$avatar = $xpath->evaluate("atom:author/atom:link[@rel='avatar']")->item(0)->attributes;
if (is_object($avatar)) {
foreach ($avatar AS $attributes) {
if ($attributes->name == "href") {
$author["author-avatar"] = $attributes->textContent;
foreach ($avatar AS $attribute) {
if ($attribute->name == "href") {
$author["author-avatar"] = $attribute->textContent;
}
}
}
@ -207,13 +208,10 @@ class Feed {
}
$items = [];
// Importing older entries first
for($i = $entries->length - 1; $i >= 0;--$i) {
$entry = $entries->item($i);
$entrylist = [];
foreach ($entries AS $entry) {
$entrylist[] = $entry;
}
foreach (array_reverse($entrylist) AS $entry) {
$item = array_merge($header, $author);
$alternate = $xpath->query("atom:link[@rel='alternate']", $entry)->item(0)->attributes;
@ -221,9 +219,9 @@ class Feed {
$alternate = $xpath->query("atom:link", $entry)->item(0)->attributes;
}
if (is_object($alternate)) {
foreach ($alternate AS $attributes) {
if ($attributes->name == "href") {
$item["plink"] = $attributes->textContent;
foreach ($alternate AS $attribute) {
if ($attribute->name == "href") {
$item["plink"] = $attribute->textContent;
}
}
}
@ -309,20 +307,20 @@ class Feed {
$attachments = [];
$enclosures = $xpath->query("enclosure", $entry);
$enclosures = $xpath->query("enclosure|atom:link[@rel='enclosure']", $entry);
foreach ($enclosures AS $enclosure) {
$href = "";
$length = "";
$type = "";
$title = "";
foreach ($enclosure->attributes AS $attributes) {
if ($attributes->name == "url") {
$href = $attributes->textContent;
} elseif ($attributes->name == "length") {
$length = $attributes->textContent;
} elseif ($attributes->name == "type") {
$type = $attributes->textContent;
foreach ($enclosure->attributes AS $attribute) {
if (in_array($attribute->name, ["url", "href"])) {
$href = $attribute->textContent;
} elseif ($attribute->name == "length") {
$length = $attribute->textContent;
} elseif ($attribute->name == "type") {
$type = $attribute->textContent;
}
}
if (strlen($item["attach"])) {
@ -363,7 +361,7 @@ class Feed {
if (self::titleIsBody($item["title"], $body)) {
$item["title"] = "";
}
$item["body"] = html2bbcode($body, $basepath);
$item["body"] = HTML::toBBCode($body, $basepath);
if (($item["body"] == '') && ($item["title"] != '')) {
$item["body"] = $item["title"];

View file

@ -5,6 +5,7 @@
namespace Friendica\Protocol;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Core\Cache;
use Friendica\Core\Config;
use Friendica\Core\L10n;
@ -25,7 +26,6 @@ use DOMDocument;
use DOMXPath;
require_once 'include/dba.php';
require_once 'include/html2bbcode.php';
require_once 'include/items.php';
require_once 'mod/share.php';
require_once 'include/enotify.php';
@ -72,8 +72,9 @@ class OStatus
$contact = null;
if ($aliaslink != '') {
$condition = ["`uid` = ? AND `alias` = ? AND `network` != ?",
$importer["uid"], $aliaslink, NETWORK_STATUSNET];
$condition = ["`uid` = ? AND `alias` = ? AND `network` != ? AND `rel` IN (?, ?)",
$importer["uid"], $aliaslink, NETWORK_STATUSNET,
CONTACT_IS_SHARING, CONTACT_IS_FRIEND];
$contact = dba::selectFirst('contact', [], $condition);
}
@ -82,14 +83,16 @@ class OStatus
$aliaslink = $author["author-link"];
}
$condition = ["`uid` = ? AND `nurl` IN (?, ?) AND `network` != ?", $importer["uid"],
normalise_link($author["author-link"]), normalise_link($aliaslink), NETWORK_STATUSNET];
$condition = ["`uid` = ? AND `nurl` IN (?, ?) AND `network` != ? AND `rel` IN (?, ?)",
$importer["uid"], normalise_link($author["author-link"]), normalise_link($aliaslink),
NETWORK_STATUSNET, CONTACT_IS_SHARING, CONTACT_IS_FRIEND];
$contact = dba::selectFirst('contact', [], $condition);
}
if (!DBM::is_result($contact) && ($addr != '')) {
$condition = ["`uid` = ? AND `addr` = ? AND `network` != ?",
$importer["uid"], $addr, NETWORK_STATUSNET];
$condition = ["`uid` = ? AND `addr` = ? AND `network` != ? AND `rel` IN (?, ?)",
$importer["uid"], $addr, NETWORK_STATUSNET,
CONTACT_IS_SHARING, CONTACT_IS_FRIEND];
$contact = dba::selectFirst('contact', [], $condition);
}
@ -168,7 +171,7 @@ class OStatus
$value = $xpath->evaluate('atom:author/poco:note/text()', $context)->item(0)->nodeValue;
if ($value != "") {
$contact["about"] = html2bbcode($value);
$contact["about"] = HTML::toBBCode($value);
}
$value = $xpath->evaluate('atom:author/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
@ -243,13 +246,12 @@ class OStatus
$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
$entries = $xpath->query('/atom:entry');
$contact = ["id" => 0];
foreach ($entries as $entry) {
// fetch the author
$author = self::fetchAuthor($xpath, $entry, $importer, $contact, true);
return $author;
}
// Fetch the first author
$authordata = $xpath->query('//author')->item(0);
$author = self::fetchAuthor($xpath, $authordata, $importer, $contact, true);
return $author;
}
/**
@ -557,7 +559,7 @@ class OStatus
*/
private static function processPost($xpath, $entry, &$item, $importer)
{
$item["body"] = html2bbcode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue);
$item["body"] = HTML::toBBCode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue);
$item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
if (($item["object-type"] == ACTIVITY_OBJ_BOOKMARK) || ($item["object-type"] == ACTIVITY_OBJ_EVENT)) {
$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
@ -658,8 +660,9 @@ class OStatus
// Mastodon Content Warning
if (($item["verb"] == ACTIVITY_POST) && $xpath->evaluate('boolean(atom:summary)', $entry)) {
$clear_text = $xpath->query('atom:summary/text()', $entry)->item(0)->nodeValue;
$item["body"] = html2bbcode($clear_text) . '[spoiler]' . $item["body"] . '[/spoiler]';
if (!empty($clear_text)) {
$item['content-warning'] = HTML::toBBCode($clear_text);
}
}
if (($self != '') && empty($item['protocol'])) {
@ -670,9 +673,11 @@ class OStatus
self::fetchConversation($item['conversation-href'], $item['conversation-uri']);
}
if (isset($item["parent-uri"]) && ($related != '')) {
if (isset($item["parent-uri"])) {
if (!dba::exists('item', ['uid' => $importer["uid"], 'uri' => $item['parent-uri']])) {
self::fetchRelated($related, $item["parent-uri"], $importer);
if ($related != '') {
self::fetchRelated($related, $item["parent-uri"], $importer);
}
} else {
logger('Reply with URI '.$item["uri"].' already existed for user '.$importer["uid"].'.', LOGGER_DEBUG);
}
@ -1014,7 +1019,7 @@ class OStatus
$item["author-link"] = $orig_author["author-link"];
$item["author-avatar"] = $orig_author["author-avatar"];
$item["body"] = html2bbcode($orig_body);
$item["body"] = HTML::toBBCode($orig_body);
$item["created"] = $orig_created;
$item["edited"] = $orig_edited;
@ -1283,6 +1288,13 @@ class OStatus
"rel" => "self", "type" => "application/atom+xml"];
XML::addElement($doc, $root, "link", "", $attributes);
if ($owner['account-type'] == ACCOUNT_TYPE_COMMUNITY) {
$condition = ['uid' => $owner['uid'], 'self' => false, 'pending' => false,
'archive' => false, 'hidden' => false, 'blocked' => false];
$members = dba::count('contact', $condition);
XML::addElement($doc, $root, "statusnet:group_info", "", ["member_count" => $members]);
}
return $root;
}
@ -1301,7 +1313,7 @@ class OStatus
}
/**
* @brief Adds attachement data to the XML document
* @brief Adds attachment data to the XML document
*
* @param object $doc XML document
* @param object $root XML root element where the hub links are added
@ -1316,11 +1328,13 @@ class OStatus
switch ($siteinfo["type"]) {
case 'photo':
$imgdata = Image::getInfoFromURL($siteinfo["image"]);
$attributes = ["rel" => "enclosure",
"href" => $siteinfo["image"],
"type" => $imgdata["mime"],
"length" => intval($imgdata["size"])];
XML::addElement($doc, $root, "link", "", $attributes);
if ($imgdata) {
$attributes = ["rel" => "enclosure",
"href" => $siteinfo["image"],
"type" => $imgdata["mime"],
"length" => intval($imgdata["size"])];
XML::addElement($doc, $root, "link", "", $attributes);
}
break;
case 'video':
$attributes = ["rel" => "enclosure",
@ -1336,12 +1350,14 @@ class OStatus
if (!Config::get('system', 'ostatus_not_attach_preview') && ($siteinfo["type"] != "photo") && isset($siteinfo["image"])) {
$imgdata = Image::getInfoFromURL($siteinfo["image"]);
$attributes = ["rel" => "enclosure",
"href" => $siteinfo["image"],
"type" => $imgdata["mime"],
"length" => intval($imgdata["size"])];
if ($imgdata) {
$attributes = ["rel" => "enclosure",
"href" => $siteinfo["image"],
"type" => $imgdata["mime"],
"length" => intval($imgdata["size"])];
XML::addElement($doc, $root, "link", "", $attributes);
XML::addElement($doc, $root, "link", "", $attributes);
}
}
$arr = explode('[/attach],', $item['attach']);
@ -1374,16 +1390,22 @@ class OStatus
*
* @return object author element
*/
private static function addAuthor($doc, $owner)
private static function addAuthor($doc, $owner, $show_profile = true)
{
$profile = dba::selectFirst('profile', ['homepage', 'publish'], ['uid' => $owner['uid'], 'is-default' => true]);
$author = $doc->createElement("author");
XML::addElement($doc, $author, "id", $owner["url"]);
XML::addElement($doc, $author, "activity:object-type", ACTIVITY_OBJ_PERSON);
if ($owner['account-type'] == ACCOUNT_TYPE_COMMUNITY) {
XML::addElement($doc, $author, "activity:object-type", ACTIVITY_OBJ_GROUP);
} else {
XML::addElement($doc, $author, "activity:object-type", ACTIVITY_OBJ_PERSON);
}
XML::addElement($doc, $author, "uri", $owner["url"]);
XML::addElement($doc, $author, "name", $owner["nick"]);
XML::addElement($doc, $author, "email", $owner["addr"]);
XML::addElement($doc, $author, "summary", BBCode::convert($owner["about"], false, 7));
if ($show_profile) {
XML::addElement($doc, $author, "summary", BBCode::convert($owner["about"], false, 7));
}
$attributes = ["rel" => "alternate", "type" => "text/html", "href" => $owner["url"]];
XML::addElement($doc, $author, "link", "", $attributes);
@ -1408,15 +1430,17 @@ class OStatus
XML::addElement($doc, $author, "poco:preferredUsername", $owner["nick"]);
XML::addElement($doc, $author, "poco:displayName", $owner["name"]);
XML::addElement($doc, $author, "poco:note", BBCode::convert($owner["about"], false, 7));
if ($show_profile) {
XML::addElement($doc, $author, "poco:note", BBCode::convert($owner["about"], false, 7));
if (trim($owner["location"]) != "") {
$element = $doc->createElement("poco:address");
XML::addElement($doc, $element, "poco:formatted", $owner["location"]);
$author->appendChild($element);
if (trim($owner["location"]) != "") {
$element = $doc->createElement("poco:address");
XML::addElement($doc, $element, "poco:formatted", $owner["location"]);
$author->appendChild($element);
}
}
if (DBM::is_result($profile)) {
if (DBM::is_result($profile) && !$show_profile) {
if (trim($profile["homepage"]) != "") {
$urls = $doc->createElement("poco:urls");
XML::addElement($doc, $urls, "poco:type", "homepage");
@ -1427,11 +1451,12 @@ class OStatus
XML::addElement($doc, $author, "followers", "", ["url" => System::baseUrl()."/viewcontacts/".$owner["nick"]]);
XML::addElement($doc, $author, "statusnet:profile_info", "", ["local_id" => $owner["uid"]]);
if ($profile["publish"]) {
XML::addElement($doc, $author, "mastodon:scope", "public");
}
}
if ($profile["publish"]) {
XML::addElement($doc, $author, "mastodon:scope", "public");
}
return $author;
}
@ -1593,7 +1618,7 @@ class OStatus
logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
}
$title = self::entryHeader($doc, $entry, $owner, $toplevel);
$title = self::entryHeader($doc, $entry, $owner, $item, $toplevel);
$r = q(
"SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' AND NOT `private` AND `network` IN ('%s', '%s', '%s') LIMIT 1",
@ -1622,7 +1647,7 @@ class OStatus
self::entryContent($doc, $as_object, $repeated_item, $owner, "", "", false);
$author = self::addAuthor($doc, $contact);
$author = self::addAuthor($doc, $contact, false);
$as_object->appendChild($author);
$as_object2 = $doc->createElement("activity:object");
@ -1664,7 +1689,7 @@ class OStatus
logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
}
$title = self::entryHeader($doc, $entry, $owner, $toplevel);
$title = self::entryHeader($doc, $entry, $owner, $item, $toplevel);
$verb = NAMESPACE_ACTIVITY_SCHEMA."favorite";
self::entryContent($doc, $entry, $item, $owner, "Favorite", $verb, false);
@ -1787,7 +1812,7 @@ class OStatus
$item["body"] = sprintf($message, $owner["nick"], $contact["nick"]);
self::entryHeader($doc, $entry, $owner, $toplevel);
self::entryHeader($doc, $entry, $owner, $item, $toplevel);
self::entryContent($doc, $entry, $item, $owner, $title);
@ -1815,7 +1840,7 @@ class OStatus
logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
}
$title = self::entryHeader($doc, $entry, $owner, $toplevel);
$title = self::entryHeader($doc, $entry, $owner, $item, $toplevel);
XML::addElement($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
@ -1836,12 +1861,18 @@ class OStatus
*
* @return string The title for the element
*/
private static function entryHeader($doc, &$entry, $owner, $toplevel)
private static function entryHeader($doc, &$entry, $owner, $item, $toplevel)
{
/// @todo Check if this title stuff is really needed (I guess not)
if (!$toplevel) {
$entry = $doc->createElement("entry");
$title = sprintf("New note by %s", $owner["nick"]);
if ($owner['account-type'] == ACCOUNT_TYPE_COMMUNITY) {
$contact = self::contactEntry($item['author-link'], $owner);
$author = self::addAuthor($doc, $contact, false);
$entry->appendChild($author);
}
} else {
$entry = $doc->createElementNS(NAMESPACE_ATOM1, "entry");
@ -1996,12 +2027,10 @@ class OStatus
$mentioned = $newmentions;
foreach ($mentioned as $mention) {
$r = q(
"SELECT `forum`, `prv` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'",
intval($owner["uid"]),
dbesc(normalise_link($mention))
);
if ($r[0]["forum"] || $r[0]["prv"]) {
$condition = ['uid' => $owner['uid'], 'nurl' => normalise_link($mention)];
$contact = dba::selectFirst('contact', ['forum', 'prv', 'self', 'contact-type'], $condition);
if ($contact["forum"] || $contact["prv"] || ($owner['contact-type'] == ACCOUNT_TYPE_COMMUNITY) ||
($contact['self'] && ($owner['account-type'] == ACCOUNT_TYPE_COMMUNITY))) {
XML::addElement($doc, $entry, "link", "",
[
"rel" => "mentioned",
@ -2018,6 +2047,12 @@ class OStatus
}
}
if ($owner['account-type'] == ACCOUNT_TYPE_COMMUNITY) {
XML::addElement($doc, $entry, "link", "", ["rel" => "mentioned",
"ostatus:object-type" => "http://activitystrea.ms/schema/1.0/group",
"href" => $owner['url']]);
}
if (!$item["private"]) {
XML::addElement($doc, $entry, "link", "", ["rel" => "ostatus:attention",
"href" => "http://activityschema.org/collection/public"]);
@ -2094,7 +2129,7 @@ class OStatus
}
$owner = dba::fetch_first(
"SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
"SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`, `user`.`account-type`
FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
WHERE `contact`.`self` AND `user`.`nickname` = ? LIMIT 1",
$owner_nick
@ -2119,22 +2154,23 @@ class OStatus
$sql_extra .= sprintf(" AND `item`.`object-type` = '%s' ", dbesc(ACTIVITY_OBJ_COMMENT));
}
if ($owner['account-type'] != ACCOUNT_TYPE_COMMUNITY) {
$sql_extra .= sprintf(" AND `item`.`contact-id` = %d AND `item`.`author-id` = %d ", intval($owner["id"]), intval($authorid));
}
$items = q(
"SELECT `item`.*, `item`.`id` AS `item_id` FROM `item` USE INDEX (`uid_contactid_created`)
STRAIGHT_JOIN `thread` ON `thread`.`iid` = `item`.`parent`
WHERE `item`.`uid` = %d
AND `item`.`contact-id` = %d
AND `item`.`author-id` = %d
AND `item`.`created` > '%s'
AND NOT `item`.`deleted`
AND NOT `item`.`private`
AND `item`.`visible`
AND `item`.`wall`
AND `thread`.`network` IN ('%s', '%s')
$sql_extra
ORDER BY `item`.`created` DESC LIMIT %d",
intval($owner["uid"]),
intval($owner["id"]),
intval($authorid),
dbesc($check_date),
dbesc(NETWORK_OSTATUS),
dbesc(NETWORK_DFRN),

View file

@ -9,6 +9,7 @@
namespace Friendica\Protocol;
use Friendica\Content\Text\HTML;
use Friendica\Core\Config;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
@ -23,7 +24,6 @@ use DOMXPath;
use Exception;
require_once 'include/dba.php';
require_once 'include/html2bbcode.php';
class PortableContact
{
@ -155,7 +155,7 @@ class PortableContact
}
if (isset($entry->aboutMe)) {
$about = html2bbcode($entry->aboutMe);
$about = HTML::toBBCode($entry->aboutMe);
}
if (isset($entry->gender)) {
@ -945,6 +945,15 @@ class PortableContact
$register_policy = $gserver["register_policy"];
$registered_users = $gserver["registered-users"];
// See discussion under https://forum.friendi.ca/display/0b6b25a8135aabc37a5a0f5684081633
// It can happen that a zero date is in the database, but storing it again is forbidden.
if ($last_contact < NULL_DATE) {
$last_contact = NULL_DATE;
}
if ($last_failure < NULL_DATE) {
$last_failure = NULL_DATE;
}
if (!$force && !self::updateNeeded($gserver["created"], "", $last_failure, $last_contact)) {
logger("Use cached data for server ".$server_url, LOGGER_DEBUG);
return ($last_contact >= $last_failure);
@ -1302,7 +1311,7 @@ class PortableContact
if (isset($data->version)) {
$network = NETWORK_DFRN;
$noscrape = $data->no_scrape_url;
$noscrape = defaults($data->no_scrape_url, '');
$version = $data->version;
$site_name = $data->site_name;
$info = $data->info;
@ -1368,11 +1377,60 @@ class PortableContact
$fields['created'] = DateTimeFormat::utcNow();
dba::insert('gserver', $fields);
}
if (!$failure && in_array($fields['network'], [NETWORK_DFRN, NETWORK_DIASPORA])) {
self::discoverRelay($server_url);
}
logger("End discovery for server " . $server_url, LOGGER_DEBUG);
return !$failure;
}
/**
* @brief Fetch relay data from a given server url
*
* @param string $server_url address of the server
*/
private static function discoverRelay($server_url)
{
logger("Discover relay data for server " . $server_url, LOGGER_DEBUG);
$serverret = Network::curl($server_url."/.well-known/x-social-relay");
if (!$serverret["success"]) {
return;
}
$data = json_decode($serverret['body']);
if (!is_object($data)) {
return;
}
$gserver = dba::selectFirst('gserver', ['id', 'relay-subscribe', 'relay-scope'], ['nurl' => normalise_link($server_url)]);
if (!DBM::is_result($gserver)) {
return;
}
if (($gserver['relay-subscribe'] != $data->subscribe) || ($gserver['relay-scope'] != $data->scope)) {
$fields = ['relay-subscribe' => $data->subscribe, 'relay-scope' => $data->scope];
dba::update('gserver', $fields, ['id' => $gserver['id']]);
}
dba::delete('gserver-tag', ['gserver-id' => $gserver['id']]);
if ($data->scope == 'tags') {
// Avoid duplicates
$tags = [];
foreach ($data->tags as $tag) {
$tag = strtolower($tag);
$tags[$tag] = $tag;
}
foreach ($tags as $tag) {
dba::insert('gserver-tag', ['gserver-id' => $gserver['id'], 'tag' => $tag]);
}
}
}
/**
* @brief Returns a list of all known servers
* @return array List of server urls
@ -1454,8 +1512,8 @@ class PortableContact
$header = ['Authorization: Bearer '.$accesstoken];
$serverdata = Network::curl($api, false, $redirects, ['headers' => $header]);
if ($serverdata['success']) {
$servers = json_decode($serverdata['body']);
foreach ($servers->instances as $server) {
$servers = json_decode($serverdata['body']);
foreach ($servers->instances as $server) {
$url = (is_null($server->https_score) ? 'http' : 'https').'://'.$server->name;
Worker::add(PRIORITY_LOW, "DiscoverPoCo", "server", $url);
}
@ -1669,7 +1727,7 @@ class PortableContact
}
if (isset($entry->aboutMe)) {
$about = html2bbcode($entry->aboutMe);
$about = HTML::toBBCode($entry->aboutMe);
}
if (isset($entry->gender)) {