* @todo Detect if it is a forum
*/
+use \Friendica\Core\Config;
+
require_once('include/datetime.php');
require_once("include/Scrape.php");
require_once("include/network.php");
if (isset($entry->contactType) AND ($entry->contactType >= 0))
$contact_type = $entry->contactType;
- // If you query a Friendica server for its profiles, the network has to be Friendica
- /// TODO It could also be a Redmatrix server
- //if ($uid == 0)
- // $network = NETWORK_DFRN;
-
- poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, $cid, $uid, $zcid);
+ $gcontact = array("url" => $profile_url,
+ "name" => $name,
+ "network" => $network,
+ "photo" => $profile_photo,
+ "about" => $about,
+ "location" => $location,
+ "gender" => $gender,
+ "keywords" => $keywords,
+ "connect" => $connect_url,
+ "updated" => $updated,
+ "contact-type" => $contact_type,
+ "generation" => $generation);
- $gcontact = array("url" => $profile_url, "contact-type" => $contact_type, "generation" => $generation);
- update_gcontact($gcontact);
+ try {
+ $gcontact = sanitize_gcontact($gcontact);
+ $gcid = update_gcontact($gcontact);
- // Update the Friendica contacts. Diaspora is doing it via a message. (See include/diaspora.php)
- // Deactivated because we now update Friendica contacts in dfrn.php
- //if (($location != "") OR ($about != "") OR ($keywords != "") OR ($gender != ""))
- // q("UPDATE `contact` SET `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s'
- // WHERE `nurl` = '%s' AND NOT `self` AND `network` = '%s'",
- // dbesc($location),
- // dbesc($about),
- // dbesc($keywords),
- // dbesc($gender),
- // dbesc(normalise_link($profile_url)),
- // dbesc(NETWORK_DFRN));
+ link_gcontact($gcid, $uid, $cid, $zcid);
+ } catch (Exception $e) {
+ logger($e->getMessage(), LOGGER_DEBUG);
+ }
}
logger("poco_load: loaded $total entries",LOGGER_DEBUG);
}
/**
- * @brief Validate the given gcontact data
+ * @brief Sanitize the given gcontact data
*
* @param array $gcontact array with gcontact data
- * @param integer $cid Contact ID
- * @param integer $uid User ID
- * @param integer $zcid Global Contact ID
+ * @throw Exception
*
* Generation:
* 0: No definition
* 4: ...
*
*/
-function validate_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'];
$gcontact["server_url"] = $data["baseurl"];
- unset($data["guid"]);
- unset($data["batch"]);
- unset($data["poll"]);
- unset($data["request"]);
- unset($data["confirm"]);
- unset($data["poco"]);
- unset($data["priority"]);
- unset($data["pubkey"]);
- unset($data["baseurl"]);
-
$gcontact = array_merge($gcontact, $data);
if ($alternate AND ($gcontact['network'] == NETWORK_OSTATUS)) {
}
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;
}
-function poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, $cid = 0, $uid = 0, $zcid = 0) {
-
- // Generation:
- // 0: No definition
- // 1: Profiles on this server
- // 2: Contacts of profiles on this server
- // 3: Contacts of contacts of profiles on this server
- // 4: ...
-
- $gcid = "";
-
- if ($profile_url == "")
- return $gcid;
-
- $urlparts = parse_url($profile_url);
- if (!isset($urlparts["scheme"]))
- return $gcid;
-
- if (in_array($urlparts["host"], array("www.facebook.com", "facebook.com", "twitter.com",
- "identi.ca", "alpha.app.net")))
- return $gcid;
-
- // Don't store the statusnet connector as network
- // We can't simply set this to NETWORK_OSTATUS since the connector could have fetched posts from friendica as well
- if ($network == NETWORK_STATUSNET)
- $network = "";
-
- // Assure that there are no parameter fragments in the profile url
- if (in_array($network, array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, "")))
- $profile_url = clean_contact_url($profile_url);
-
- $alternate = poco_alternate_ostatus_url($profile_url);
-
- $orig_updated = $updated;
-
- // The global contacts should contain the original picture, not the cached one
- if (($generation != 1) AND stristr(normalise_link($profile_photo), normalise_link(App::get_baseurl()."/photo/"))) {
- $profile_photo = "";
- }
-
- $r = q("SELECT `network` FROM `contact` WHERE `nurl` = '%s' AND `network` != '' AND `network` != '%s' LIMIT 1",
- dbesc(normalise_link($profile_url)), dbesc(NETWORK_STATUSNET)
- );
- if (dbm::is_result($r)) {
- $network = $r[0]["network"];
- }
-
- if (($network == "") OR ($network == NETWORK_OSTATUS)) {
- $r = q("SELECT `network`, `url` FROM `contact` WHERE `alias` IN ('%s', '%s') AND `network` != '' AND `network` != '%s' LIMIT 1",
- dbesc($profile_url), dbesc(normalise_link($profile_url)), dbesc(NETWORK_STATUSNET)
- );
- if (dbm::is_result($r)) {
- $network = $r[0]["network"];
- //$profile_url = $r[0]["url"];
- }
- }
-
- $x = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
- dbesc(normalise_link($profile_url))
- );
-
- if (count($x)) {
- if (($network == "") AND ($x[0]["network"] != NETWORK_STATUSNET)) {
- $network = $x[0]["network"];
- }
- if ($updated <= NULL_DATE) {
- $updated = $x[0]["updated"];
- }
- $created = $x[0]["created"];
- $server_url = $x[0]["server_url"];
- $nick = $x[0]["nick"];
- $addr = $x[0]["addr"];
- $alias = $x[0]["alias"];
- $notify = $x[0]["notify"];
- } else {
- $created = NULL_DATE;
- $server_url = "";
-
- $urlparts = parse_url($profile_url);
- $nick = end(explode("/", $urlparts["path"]));
- $addr = "";
- $alias = "";
- $notify = "";
- }
-
- if ((($network == "") OR ($name == "") OR ($addr == "") OR ($profile_photo == "") OR ($server_url == "") OR $alternate)
- AND poco_reachable($profile_url, $server_url, $network, false)) {
- $data = probe_url($profile_url);
-
- $orig_profile = $profile_url;
-
- $network = $data["network"];
- $name = $data["name"];
- $nick = $data["nick"];
- $addr = $data["addr"];
- $alias = $data["alias"];
- $notify = $data["notify"];
- $profile_url = $data["url"];
- $profile_photo = $data["photo"];
- $server_url = $data["baseurl"];
-
- if ($alternate AND ($network == NETWORK_OSTATUS)) {
- // Delete the old entry - if it exists
- $r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile)));
- if ($r) {
- q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile)));
- q("DELETE FROM `glink` WHERE `gcid` = %d", intval($r[0]["id"]));
- }
-
- // possibly create a new entry
- poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, $cid, $uid, $zcid);
- }
- }
-
- if ($alternate AND ($network == NETWORK_OSTATUS))
- return $gcid;
-
- if (count($x) AND ($x[0]["network"] == "") AND ($network != "")) {
- q("UPDATE `gcontact` SET `network` = '%s' WHERE `nurl` = '%s'",
- dbesc($network),
- dbesc(normalise_link($profile_url))
- );
- }
-
- if (($name == "") OR ($profile_photo == ""))
- return $gcid;
-
- if (!in_array($network, array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)))
- return $gcid;
-
- logger("profile-check generation: ".$generation." Network: ".$network." URL: ".$profile_url." name: ".$name." avatar: ".$profile_photo, LOGGER_DEBUG);
-
- // We check the server url to be sure that it is a real one
- $server_url2 = poco_detect_server($profile_url);
+/**
+ * @brief Link the gcontact entry with user, contact and global contact
+ *
+ * @param integer $gcid Global contact ID
+ * @param integer $cid Contact ID
+ * @param integer $uid User ID
+ * @param integer $zcid Global Contact ID
+ * *
+ */
+function link_gcontact($gcid, $uid = 0, $cid = 0, $zcid = 0) {
- // We are no sure that it is a correct URL. So we use it in the future
- if ($server_url2 != "") {
- $server_url = $server_url2;
+ if ($gcid <= 0) {
+ return;
}
- // The server URL doesn't seem to be valid, so we don't store it.
- if (!poco_check_server($server_url, $network)) {
- $server_url = "";
- }
-
- $gcontact = array("url" => $profile_url,
- "addr" => $addr,
- "alias" => $alias,
- "name" => $name,
- "network" => $network,
- "photo" => $profile_photo,
- "about" => $about,
- "location" => $location,
- "gender" => $gender,
- "keywords" => $keywords,
- "server_url" => $server_url,
- "connect" => $connect_url,
- "notify" => $notify,
- "updated" => $updated,
- "generation" => $generation);
-
- $gcid = update_gcontact($gcontact);
-
- if(!$gcid)
- return $gcid;
-
- link_gcontact($gcid, $uid, $cid, $zcid);
-
- return $gcid;
-}
-
-function link_gcontact($gcid, $uid = 0, $cid = 0, $zcid = 0) {
$r = q("SELECT * FROM `glink` WHERE `cid` = %d AND `uid` = %d AND `gcid` = %d AND `zcid` = %d LIMIT 1",
intval($cid),
intval($uid),
$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 ($gcontacts[0]["server_url"] != "") {
+
+ if ($force) {
+ $server_url = normalise_link(poco_detect_server($profile));
+ }
+
+ 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"];
}
q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($profile)));
q("DELETE FROM `glink` WHERE `gcid` = %d", intval($gcontacts[0]["id"]));
- poco_check($data["url"], $data["name"], $data["network"], $data["photo"], $gcontacts[0]["about"], $gcontacts[0]["location"],
- $gcontacts[0]["gender"], $gcontacts[0]["keywords"], $data["addr"], $gcontacts[0]["updated"], $gcontacts[0]["generation"]);
+ $gcontact = array_merge($gcontacts[0], $data);
+
+ $gcontact["server_url"] = $data["baseurl"];
+
+ try {
+ $gcontact = sanitize_gcontact($gcontact);
+ update_gcontact($gcontact);
- poco_last_updated($data["url"], $force);
+ poco_last_updated($data["url"], $force);
+ } catch (Exception $e) {
+ logger($e->getMessage(), LOGGER_DEBUG);
+ }
logger("Profile ".$profile." was deleted", LOGGER_DEBUG);
return false;
return false;
}
- $contact = array("generation" => $gcontacts[0]["generation"]);
-
$contact = array_merge($contact, $data);
$contact["server_url"] = $data["baseurl"];
- unset($contact["guid"]);
- unset($contact["batch"]);
- unset($contact["poll"]);
- unset($contact["request"]);
- unset($contact["confirm"]);
- unset($contact["poco"]);
- unset($contact["priority"]);
- unset($contact["pubkey"]);
- unset($contact["baseurl"]);
-
update_gcontact($contact);
$feedret = z_fetch_url($data["poll"]);
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);
}
}
+ // 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 (validate_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);
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;
}
+ $data["server_url"] = $data["baseurl"];
+
update_gcontact($data);
}