+ // Directory types
+ const DT_NONE = 0;
+ const DT_POCO = 1;
+ const DT_MASTODON = 2;
+ /**
+ * Checks if the given server is reachable
+ *
+ * @param string $profile URL of the given profile
+ * @param string $server URL of the given server (If empty, taken from profile)
+ * @param string $network Network value that is used, when detection failed
+ * @param boolean $force Force an update.
+ *
+ * @return boolean 'true' if server seems vital
+ */
+ public static function reachable(string $profile, string $server = '', string $network = '', bool $force = false)
+ {
+ if ($server == '') {
+ $server = GContact::getBasepath($profile);
+ }
+
+ if ($server == '') {
+ return true;
+ }
+
+ return self::check($server, $network, $force);
+ }
+
+ /**
+ * Decides if a server needs to be updated, based upon several date fields
+ *
+ * @param date $created Creation date of that server entry
+ * @param date $updated When had the server entry be updated
+ * @param date $last_failure Last failure when contacting that server
+ * @param date $last_contact Last time the server had been contacted
+ *
+ * @return boolean Does the server record needs an update?
+ */
+ public static function updateNeeded($created, $updated, $last_failure, $last_contact)
+ {
+ $now = strtotime(DateTimeFormat::utcNow());
+
+ if ($updated > $last_contact) {
+ $contact_time = strtotime($updated);
+ } else {
+ $contact_time = strtotime($last_contact);
+ }
+
+ $failure_time = strtotime($last_failure);
+ $created_time = strtotime($created);
+
+ // If there is no "created" time then use the current time
+ if ($created_time <= 0) {
+ $created_time = $now;
+ }
+
+ // If the last contact was less than 24 hours then don't update
+ if (($now - $contact_time) < (60 * 60 * 24)) {
+ return false;
+ }
+
+ // If the last failure was less than 24 hours then don't update
+ if (($now - $failure_time) < (60 * 60 * 24)) {
+ return false;
+ }
+
+ // If the last contact was less than a week ago and the last failure is older than a week then don't update
+ //if ((($now - $contact_time) < (60 * 60 * 24 * 7)) && ($contact_time > $failure_time))
+ // return false;
+
+ // If the last contact time was more than a week ago and the contact was created more than a week ago, then only try once a week
+ if ((($now - $contact_time) > (60 * 60 * 24 * 7)) && (($now - $created_time) > (60 * 60 * 24 * 7)) && (($now - $failure_time) < (60 * 60 * 24 * 7))) {
+ return false;
+ }
+
+ // If the last contact time was more than a month ago and the contact was created more than a month ago, then only try once a month
+ if ((($now - $contact_time) > (60 * 60 * 24 * 30)) && (($now - $created_time) > (60 * 60 * 24 * 30)) && (($now - $failure_time) < (60 * 60 * 24 * 30))) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks the state of the given server.
+ *
+ * @param string $server_url URL of the given server
+ * @param string $network Network value that is used, when detection failed
+ * @param boolean $force Force an update.
+ *
+ * @return boolean 'true' if server seems vital
+ */
+ public static function check(string $server_url, string $network = '', bool $force = false)
+ {
+ // Unify the server address
+ $server_url = trim($server_url, '/');
+ $server_url = str_replace('/index.php', '', $server_url);
+
+ if ($server_url == '') {
+ return false;
+ }
+
+ $gserver = DBA::selectFirst('gserver', [], ['nurl' => Strings::normaliseLink($server_url)]);
+ if (DBA::isResult($gserver)) {
+ if ($gserver['created'] <= DBA::NULL_DATETIME) {
+ $fields = ['created' => DateTimeFormat::utcNow()];
+ $condition = ['nurl' => Strings::normaliseLink($server_url)];
+ DBA::update('gserver', $fields, $condition);
+ }
+
+ $last_contact = $gserver['last_contact'];
+ $last_failure = $gserver['last_failure'];
+
+ // 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 < DBA::NULL_DATETIME) {
+ $last_contact = DBA::NULL_DATETIME;
+ }
+
+ if ($last_failure < DBA::NULL_DATETIME) {
+ $last_failure = DBA::NULL_DATETIME;
+ }
+
+ if (!$force && !self::updateNeeded($gserver['created'], '', $last_failure, $last_contact)) {
+ Logger::info('No update needed', ['server' => $server_url]);
+ return ($last_contact >= $last_failure);
+ }
+ Logger::info('Server is outdated. Start discovery.', ['Server' => $server_url, 'Force' => $force, 'Created' => $gserver['created'], 'Failure' => $last_failure, 'Contact' => $last_contact]);
+ } else {
+ Logger::info('Server is unknown. Start discovery.', ['Server' => $server_url]);
+ }
+
+ return self::detect($server_url, $network);
+ }
+