<?php
/**
* @file include/socgraph.php
- *
+ *
* @todo Move GNU Social URL schemata (http://server.tld/user/number) to http://server.tld/username
* @todo Fetch profile data from profile page for Redmatrix users
* @todo Detect if it is a forum
*/
-require_once('include/datetime.php');
-require_once("include/Scrape.php");
-require_once("include/network.php");
-require_once("include/html2bbcode.php");
-require_once("include/Contact.php");
-require_once("include/Photo.php");
+use Friendica\App;
+use Friendica\Core\Config;
+use Friendica\Network\Probe;
+
+require_once 'include/datetime.php';
+require_once 'include/probe.php';
+require_once 'include/network.php';
+require_once 'include/html2bbcode.php';
+require_once 'include/Contact.php';
+require_once 'include/Photo.php';
/**
* @brief Fetch POCO data
"contact-type" => $contact_type,
"generation" => $generation);
- if (sanitized_gcontact($gcontact)) {
+ try {
+ $gcontact = sanitize_gcontact($gcontact);
$gcid = update_gcontact($gcontact);
link_gcontact($gcid, $uid, $cid, $zcid);
+ } catch (Exception $e) {
+ logger($e->getMessage(), LOGGER_DEBUG);
}
}
logger("poco_load: loaded $total entries",LOGGER_DEBUG);
* @brief Sanitize the given gcontact data
*
* @param array $gcontact array with gcontact data
+ * @throw Exception
*
* Generation:
* 0: No definition
* 4: ...
*
*/
-function sanitized_gcontact(&$gcontact) {
+function sanitize_gcontact($gcontact) {
if ($gcontact['url'] == "") {
- return false;
+ throw new Exception('URL is empty');
}
$urlparts = parse_url($gcontact['url']);
if (!isset($urlparts["scheme"])) {
- return false;
+ throw new Exception("This (".$gcontact['url'].") doesn't seem to be an url.");
}
if (in_array($urlparts["host"], array("www.facebook.com", "facebook.com", "twitter.com",
"identi.ca", "alpha.app.net"))) {
- return false;
+ throw new Exception('Contact from a non federated network ignored. ('.$gcontact['url'].')');
}
// Don't store the statusnet connector as network
}
}
+ $gcontact['server_url'] = '';
+ $gcontact['network'] = '';
+
$x = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
dbesc(normalise_link($gcontact['url']))
);
if ($gcontact['updated'] <= NULL_DATE) {
$gcontact['updated'] = $x[0]["updated"];
}
- if (!isset($gcontact['server_url'])) {
+ if (!isset($gcontact['server_url']) AND (normalise_link($x[0]["server_url"]) != normalise_link($x[0]["url"]))) {
$gcontact['server_url'] = $x[0]["server_url"];
}
if (!isset($gcontact['addr'])) {
$gcontact['addr'] = $x[0]["addr"];
}
- } else {
- if (!isset($gcontact['server_url'])) {
- $gcontact['server_url'] = '';
- }
- if (!isset($gcontact['network'])) {
- $gcontact['network'] = '';
- }
}
if ((!isset($gcontact['network']) OR !isset($gcontact['name']) OR !isset($gcontact['addr']) OR !isset($gcontact['photo']) OR !isset($gcontact['server_url']) OR $alternate)
$data = Probe::uri($gcontact['url']);
if ($data["network"] == NETWORK_PHANTOM) {
- return false;
+ throw new Exception('Probing for URL '.$gcontact['url'].' failed');
}
$orig_profile = $gcontact['url'];
}
if (!isset($gcontact['name']) OR !isset($gcontact['photo'])) {
- return false;
+ throw new Exception('No name and photo for URL '.$gcontact['url']);
}
if (!in_array($gcontact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA))) {
- return false;
+ throw new Exception('No federated network ('.$gcontact['network'].') detected for URL '.$gcontact['url']);
}
if (!isset($gcontact['server_url'])) {
$gcontact['server_url'] = "";
}
- return true;
+ return $gcontact;
}
/**
$gcontacts = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s'",
dbesc(normalise_link($profile)));
+ if (!dbm::is_result($gcontacts)) {
+ return false;
+ }
+
+ $contact = array("url" => $profile);
+
if ($gcontacts[0]["created"] <= NULL_DATE) {
- q("UPDATE `gcontact` SET `created` = '%s' WHERE `nurl` = '%s'",
- dbesc(datetime_convert()), dbesc(normalise_link($profile)));
+ $contact['created'] = datetime_convert();
+ }
+
+ if ($force) {
+ $server_url = normalise_link(poco_detect_server($profile));
}
- if ($gcontacts[0]["server_url"] != "") {
+
+ if (($server_url == '') AND ($gcontacts[0]["server_url"] != "")) {
$server_url = $gcontacts[0]["server_url"];
}
- if (($server_url == '') OR ($gcontacts[0]["server_url"] == $gcontacts[0]["nurl"])) {
- $server_url = poco_detect_server($profile);
+
+ if (!$force AND (($server_url == '') OR ($gcontacts[0]["server_url"] == $gcontacts[0]["nurl"]))) {
+ $server_url = normalise_link(poco_detect_server($profile));
}
if (!in_array($gcontacts[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_FEED, NETWORK_OSTATUS, ""))) {
if ($server_url != "") {
if (!poco_check_server($server_url, $gcontacts[0]["network"], $force)) {
-
- if ($force)
+ if ($force) {
q("UPDATE `gcontact` SET `last_failure` = '%s' WHERE `nurl` = '%s'",
dbesc(datetime_convert()), dbesc(normalise_link($profile)));
+ }
logger("Profile ".$profile.": Server ".$server_url." wasn't reachable.", LOGGER_DEBUG);
return false;
}
-
- q("UPDATE `gcontact` SET `server_url` = '%s' WHERE `nurl` = '%s'",
- dbesc($server_url), dbesc(normalise_link($profile)));
+ $contact['server_url'] = $server_url;
}
if (in_array($gcontacts[0]["network"], array("", NETWORK_FEED))) {
$server = q("SELECT `network` FROM `gserver` WHERE `nurl` = '%s' AND `network` != ''",
dbesc(normalise_link($server_url)));
- if ($server)
- q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'",
- dbesc($server[0]["network"]), dbesc(normalise_link($profile)));
- else
+ if ($server) {
+ $contact['network'] = $server[0]["network"];
+ } else {
return false;
+ }
}
// noscrape is really fast so we don't cache the call.
- if (($gcontacts[0]["server_url"] != "") AND ($gcontacts[0]["nick"] != "")) {
+ if (($server_url != "") AND ($gcontacts[0]["nick"] != "")) {
// Use noscrape if possible
- $server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", dbesc(normalise_link($gcontacts[0]["server_url"])));
+ $server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", dbesc(normalise_link($server_url)));
if ($server) {
$noscraperet = z_fetch_url($server[0]["noscrape"]."/".$gcontacts[0]["nick"]);
- if ($noscraperet["success"] AND ($noscraperet["body"] != "")) {
+ if ($noscraperet["success"] AND ($noscraperet["body"] != "")) {
$noscrape = json_decode($noscraperet["body"], true);
if (is_array($noscrape)) {
- $contact = array("url" => $profile,
- "network" => $server[0]["network"],
- "generation" => $gcontacts[0]["generation"]);
+ $contact["network"] = $server[0]["network"];
- if (isset($noscrape["fn"]))
+ if (isset($noscrape["fn"])) {
$contact["name"] = $noscrape["fn"];
-
- if (isset($noscrape["comm"]))
+ }
+ if (isset($noscrape["comm"])) {
$contact["community"] = $noscrape["comm"];
-
+ }
if (isset($noscrape["tags"])) {
$keywords = implode(" ", $noscrape["tags"]);
- if ($keywords != "")
+ if ($keywords != "") {
$contact["keywords"] = $keywords;
+ }
}
$location = formatted_location($noscrape);
- if ($location)
+ if ($location) {
$contact["location"] = $location;
-
- if (isset($noscrape["dfrn-notify"]))
+ }
+ if (isset($noscrape["dfrn-notify"])) {
$contact["notify"] = $noscrape["dfrn-notify"];
-
+ }
// Remove all fields that are not present in the gcontact table
unset($noscrape["fn"]);
unset($noscrape["key"]);
}
// If we only can poll the feed, then we only do this once a while
- if (!$force AND !poco_do_update($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"])) {
+ if (!$force AND !poco_do_update($gcontacts[0]["created"], $gcontacts[0]["updated"], $gcontacts[0]["last_failure"], $gcontacts[0]["last_contact"])) {
logger("Profile ".$profile." was last updated at ".$gcontacts[0]["updated"]." (cached)", LOGGER_DEBUG);
+
+ update_gcontact($contact);
return $gcontacts[0]["updated"];
}
$gcontact["server_url"] = $data["baseurl"];
- if (sanitized_gcontact($gcontact)) {
+ try {
+ $gcontact = sanitize_gcontact($gcontact);
update_gcontact($gcontact);
poco_last_updated($data["url"], $force);
+ } catch (Exception $e) {
+ logger($e->getMessage(), LOGGER_DEBUG);
}
logger("Profile ".$profile." was deleted", LOGGER_DEBUG);
return false;
}
- $contact = array("generation" => $gcontacts[0]["generation"]);
-
$contact = array_merge($contact, $data);
$contact["server_url"] = $data["baseurl"];
q("UPDATE `gcontact` SET `updated` = '%s', `last_contact` = '%s' WHERE `nurl` = '%s'",
dbesc(dbm::date($last_updated)), dbesc(dbm::date()), dbesc(normalise_link($profile)));
- if (($gcontacts[0]["generation"] == 0))
+ if (($gcontacts[0]["generation"] == 0)) {
q("UPDATE `gcontact` SET `generation` = 9 WHERE `nurl` = '%s'",
dbesc(normalise_link($profile)));
+ }
logger("Profile ".$profile." was last updated at ".$last_updated, LOGGER_DEBUG);
function poco_detect_server_type($body) {
$server = false;
- $doc = new \DOMDocument();
+ $doc = new DOMDocument();
@$doc->loadHTML($body);
- $xpath = new \DomXPath($doc);
+ $xpath = new DomXPath($doc);
$list = $xpath->query("//meta[@name]");
if (dbm::is_result($servers) AND ($orig_server_url == $server_url) AND
($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG);
+ dba::p("UPDATE `gserver` SET `last_failure` = ? WHERE `nurl` = ?", datetime_convert(), normalise_link($server_url));
return false;
}
// Quit if there is a timeout
if ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT) {
logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG);
+ dba::p("UPDATE `gserver` SET `last_failure` = ? WHERE `nurl` = ?", datetime_convert(), normalise_link($server_url));
return false;
}
if (!$serverret["success"] OR ($serverret["body"] == "") OR (sizeof($xmlobj) == 0) OR !is_object($xmlobj)) {
// Workaround for bad configured servers (known nginx problem)
if (!in_array($serverret["debug"]["http_code"], array("403", "404"))) {
- $last_failure = datetime_convert();
$failure = true;
}
$possible_failure = true;
- } elseif ($network == NETWORK_DIASPORA)
- $last_contact = datetime_convert();
+ }
// If the server has no possible failure we reset the cached data
if (!$possible_failure) {
$data = json_decode($serverret["body"]);
if (isset($data->totalResults)) {
$poco = $server_url."/poco";
- $last_contact = datetime_convert();
-
$server = poco_detect_poco_data($data);
if ($server) {
$platform = $server['platform'];
$serverret = z_fetch_url($server_url);
if (!$serverret["success"] OR ($serverret["body"] == "")) {
- $last_failure = datetime_convert();
$failure = true;
} else {
$server = poco_detect_server_type($serverret["body"]);
$network = $server['network'];
$version = $server['version'];
$site_name = $server['site_name'];
- $last_contact = datetime_convert();
}
$lines = explode("\n",$serverret["header"]);
$network = NETWORK_DIASPORA;
$versionparts = explode("-", $version);
$version = $versionparts[0];
- $last_contact = datetime_convert();
}
if(stristr($line,'Server: Mastodon')) {
$platform = "Mastodon";
$network = NETWORK_OSTATUS;
- // Mastodon doesn't reveal version numbers
- $version = "";
- $last_contact = datetime_convert();
}
}
}
$version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]);
$version = trim($version, '"');
$network = NETWORK_OSTATUS;
- $last_contact = datetime_convert();
}
// Test for GNU Social
$version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]);
$version = trim($version, '"');
$network = NETWORK_OSTATUS;
- $last_contact = datetime_convert();
+ }
+
+ // Test for Mastodon
+ $serverret = z_fetch_url($server_url."/api/v1/instance");
+ if ($serverret["success"] AND ($serverret["body"] != '')) {
+ $data = json_decode($serverret["body"]);
+ if (isset($data->version)) {
+ $platform = "Mastodon";
+ $version = $data->version;
+ $site_name = $data->title;
+ $info = $data->description;
+ $network = NETWORK_OSTATUS;
+ }
}
}
if ($serverret["success"]) {
$data = json_decode($serverret["body"]);
if (isset($data->site->server)) {
- $last_contact = datetime_convert();
-
if (isset($data->site->platform)) {
$platform = $data->site->platform->PLATFORM_NAME;
$version = $data->site->platform->STD_VERSION;
}
}
-
// Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix
if (!$failure) {
$serverret = z_fetch_url($server_url."/statistics.json");
} else {
$register_policy = REGISTER_CLOSED;
}
-
- if (isset($data->version))
- $last_contact = datetime_convert();
}
}
if (isset($server['site_name'])) {
$site_name = $server['site_name'];
}
-
- $last_contact = datetime_convert();
}
}
$data = json_decode($serverret["body"]);
if (isset($data->version)) {
- $last_contact = datetime_convert();
$network = NETWORK_DFRN;
$noscrape = $data->no_scrape_url;
}
if ($possible_failure AND !$failure) {
- $last_failure = datetime_convert();
$failure = true;
}
if ($failure) {
$last_contact = $orig_last_contact;
+ $last_failure = datetime_convert();
} else {
+ $last_contact = datetime_convert();
$last_failure = $orig_last_failure;
}
$r = q("SELECT `gcontact`.*
FROM `glink` INNER JOIN `gcontact` on `glink`.`gcid` = `gcontact`.`id`
where `glink`.`zcid` = %d
- and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 )
+ and `gcontact`.`nurl` in (select nurl from contact where uid = %d and self = 0 and blocked = 0 and hidden = 0 )
$sql_extra limit %d, %d",
intval($zcid),
intval($uid),
}
}
+ // Disvover Mastodon servers
+ if (!Config::get('system','ostatus_disabled')) {
+ $serverdata = fetch_url("https://instances.mastodon.xyz/instances.json");
+
+ if ($serverdata) {
+ $servers = json_decode($serverdata);
+
+ foreach ($servers AS $server) {
+ $url = (is_null($server->https_score) ? 'http' : 'https').'://'.$server->name;
+ proc_run(PRIORITY_LOW, "include/discover_poco.php", "server", base64_encode($url));
+ }
+ }
+ }
+
// Currently disabled, since the service isn't available anymore.
// It is not removed since I hope that there will be a successor.
// Discover GNU Social Servers.
"contact-type" => $contact_type,
"generation" => $generation);
- if (sanitized_gcontact($gcontact)) {
+ try {
+ $gcontact = sanitize_gcontact($gcontact);
update_gcontact($gcontact);
+ } catch (Exception $e) {
+ logger($e->getMessage(), LOGGER_DEBUG);
}
logger("Done for profile ".$profile_url, LOGGER_DEBUG);
if (in_array($contact["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS)))
$contact["url"] = clean_contact_url($contact["url"]);
- $r = q("SELECT `id`, `last_contact`, `last_failure`, `network` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 2",
+ dba::lock('gcontact');
+ $r = q("SELECT `id`, `last_contact`, `last_failure`, `network` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
dbesc(normalise_link($contact["url"])));
- if ($r) {
+ if (dbm::is_result($r)) {
$gcontact_id = $r[0]["id"];
// Update every 90 days
$doprobing = in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""));
}
}
+ dba::unlock();
if ($doprobing) {
logger("Last Contact: ". $last_contact_str." - Last Failure: ".$last_failure_str." - Checking: ".$contact["url"], LOGGER_DEBUG);
proc_run(PRIORITY_LOW, 'include/gprobe.php', bin2hex($contact["url"]));
}
- if ((dbm::is_result($r)) AND (count($r) > 1) AND ($gcontact_id > 0) AND ($contact["url"] != ""))
- q("DELETE FROM `gcontact` WHERE `nurl` = '%s' AND `id` != %d",
- dbesc(normalise_link($contact["url"])),
- intval($gcontact_id));
-
return $gcontact_id;
}
fix_alternate_contact_address($contact);
if (!isset($contact["updated"]))
- $contact["updated"] = datetime_convert();
+ $contact["updated"] = dbm::date();
if ($contact["server_url"] == "") {
$server_url = $contact["url"];
dbesc($contact["gender"]), dbesc($contact["keywords"]), intval($contact["hide"]),
intval($contact["nsfw"]), intval($contact["contact-type"]), dbesc($contact["alias"]),
dbesc($contact["notify"]), dbesc($contact["url"]), dbesc($contact["location"]),
- dbesc($contact["about"]), intval($contact["generation"]), dbesc($contact["updated"]),
+ dbesc($contact["about"]), intval($contact["generation"]), dbesc(dbm::date($contact["updated"])),
dbesc($contact["server_url"]), dbesc($contact["connect"]),
dbesc(normalise_link($contact["url"])), intval($contact["generation"]));
}
return $r;
}
-?>