|
|
|
<?php
|
|
|
|
$REGEX_JOIN_LINK = (function(){
|
|
|
|
// See https://github.com/oxen-io/session-pysogs/blob/dev/administration.md
|
|
|
|
$protocol = 'https?:';
|
|
|
|
$hostname = '[^\/]+';
|
|
|
|
$room_name = '[0-9A-Za-z-_]+';
|
|
|
|
$public_key = '[[:xdigit:]]{64}';
|
|
|
|
// Use pipe delimiter for regex to avoid escaping slashes.
|
|
|
|
return "|$protocol//$hostname/$room_name\?public_key=$public_key|i";
|
|
|
|
})();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param CommunityServer[] $servers
|
|
|
|
*/
|
|
|
|
function count_rooms($servers) {
|
|
|
|
$rooms_total = 0;
|
|
|
|
foreach ($servers as $server) {
|
|
|
|
$rooms_total += count($server->rooms);
|
|
|
|
}
|
|
|
|
return $rooms_total;
|
|
|
|
}
|
|
|
|
|
|
|
|
function truncate($url, $len) {
|
|
|
|
return (strlen($url) > $len + 3)
|
|
|
|
? substr($url, 0, $len).'...'
|
|
|
|
: $url;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper function for reduce_servers
|
|
|
|
*/
|
|
|
|
function url_is_reachable($url) {
|
|
|
|
global $curl_connecttimeout_ms;
|
|
|
|
global $curl_timeout_ms;
|
|
|
|
$ch = curl_init($url);
|
|
|
|
curl_setopt($ch, CURLOPT_NOBODY, true);
|
|
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS , $curl_connecttimeout_ms);
|
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT_MS, $curl_timeout_ms);
|
|
|
|
curl_exec($ch);
|
|
|
|
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
|
curl_close($ch);
|
|
|
|
|
|
|
|
log_debug($url . " is " . $retcode . ".");
|
|
|
|
return $retcode != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper function for to decide room preview link
|
|
|
|
*/
|
|
|
|
function url_is_200($url) {
|
|
|
|
global $curl_connecttimeout_ms;
|
|
|
|
global $curl_timeout_ms;
|
|
|
|
$ch = curl_init($url);
|
|
|
|
curl_setopt($ch, CURLOPT_NOBODY, true);
|
|
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS , $curl_connecttimeout_ms);
|
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT_MS, $curl_timeout_ms);
|
|
|
|
curl_exec($ch);
|
|
|
|
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
|
curl_close($ch);
|
|
|
|
|
|
|
|
log_debug($url . " is " . $retcode . ".");
|
|
|
|
|
|
|
|
return $retcode == 200;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* file_get_contents alternative that circumvents flaky routing to Chinese servers
|
|
|
|
*/
|
|
|
|
// Low default retries value so this doesn't run for 30 minutes
|
|
|
|
// FIXME: Does not seem to handle 308's, behaviour not transparent.
|
|
|
|
// TODO: Parallelize & use in CommunityServer::poll_reachable()
|
|
|
|
function curl_get_contents(string $url, $retries = 5) {
|
|
|
|
// use separate timeouts to reliably get data from Chinese server with repeated tries
|
|
|
|
$connecttimeout = 2; // wait at most X seconds to connect
|
|
|
|
$timeout = 3; // can't take longer than X seconds for the whole curl process
|
|
|
|
$sleep = 2; // sleep between tries in seconds
|
|
|
|
// takes at most ($timeout + $sleep) * $retries seconds
|
|
|
|
|
|
|
|
$contents = false;
|
|
|
|
$retcode = -1;
|
|
|
|
$counter = 1;
|
|
|
|
|
|
|
|
while(!$contents && $counter <= $retries && $retcode != 404) {
|
|
|
|
$curl = curl_init($url);
|
|
|
|
|
|
|
|
// curl_setopt($curl, CURLOPT_VERBOSE, true);
|
|
|
|
|
|
|
|
curl_setopt($curl, CURLOPT_AUTOREFERER, true);
|
|
|
|
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
|
|
|
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $connecttimeout);
|
|
|
|
curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
|
|
|
|
|
|
|
|
$contents = curl_exec($curl);
|
|
|
|
$retcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
|
|
|
|
|
|
|
curl_close($curl);
|
|
|
|
|
|
|
|
log_debug("Attempt #" . $counter . " for " . $url . " returned code " . $retcode . ".");
|
|
|
|
$counter++;
|
|
|
|
sleep($sleep);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($retcode != 200) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return $contents;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the scheme, hostname and optional port of a URL.
|
|
|
|
*/
|
|
|
|
function url_get_base(string $url, bool $include_scheme = true) {
|
|
|
|
$url_components = parse_url($url);
|
|
|
|
$scheme = $url_components['scheme'];
|
|
|
|
$host = $url_components['host'];
|
|
|
|
|
|
|
|
if (isset($url_components['port'])) {
|
|
|
|
$port = $url_components['port'];
|
|
|
|
$host .= ":$port";
|
|
|
|
}
|
|
|
|
|
|
|
|
return $include_scheme ? "$scheme://$host" : $host;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts join links that match $REGEX_JOIN_LINK.
|
|
|
|
* @return string[] Sorted array of unique server join links.
|
|
|
|
*/
|
|
|
|
function parse_join_links($html){
|
|
|
|
global $REGEX_JOIN_LINK;
|
|
|
|
preg_match_all($REGEX_JOIN_LINK, $html, $match_result);
|
|
|
|
$links = $match_result[0];
|
|
|
|
sort($links);
|
|
|
|
$links = array_unique($links);
|
|
|
|
return $links;
|
|
|
|
}
|
|
|
|
|
|
|
|
?>
|