diff --git a/html/.gitignore b/html/.gitignore new file mode 100644 index 0000000..10fba7e --- /dev/null +++ b/html/.gitignore @@ -0,0 +1 @@ +/speedtest.git/ diff --git a/html/backend/.gitignore b/html/backend/.gitignore new file mode 100644 index 0000000..776f662 --- /dev/null +++ b/html/backend/.gitignore @@ -0,0 +1 @@ +/getIP_ipInfo_apikey.php diff --git a/html/backend/country_asn.mmdb b/html/backend/country_asn.mmdb new file mode 100644 index 0000000..67dbcd9 Binary files /dev/null and b/html/backend/country_asn.mmdb differ diff --git a/html/backend/geoip2.phar b/html/backend/geoip2.phar new file mode 100644 index 0000000..197390d Binary files /dev/null and b/html/backend/geoip2.phar differ diff --git a/html/backend/getIP.php b/html/backend/getIP.php index a668f51..675224a 100644 --- a/html/backend/getIP.php +++ b/html/backend/getIP.php @@ -2,7 +2,7 @@ /* * This script detects the client's IP address and fetches ISP info from ipinfo.io/ - * Output from this script is a JSON string composed of 2 objects: a string called processedString which contains the combined IP, ISP, Country and distance as it can be presented to the user; and an object called rawIspInfo which contains the raw data from ipinfo.io (will be empty if isp detection is disabled). + * Output from this script is a JSON string composed of 2 objects: a string called processedString which contains the combined IP, ISP, Country and distance as it can be presented to the user; and an object called rawIspInfo which contains the raw data from ipinfo.io (or an empty string if isp detection is disabled or if it failed). * Client side, the output of this script can be treated as JSON or as regular text. If the output is regular text, it will be shown to the user as is. */ @@ -10,399 +10,194 @@ error_reporting(0); define('API_KEY_FILE', 'getIP_ipInfo_apikey.php'); define('SERVER_LOCATION_CACHE_FILE', 'getIP_serverLocation.php'); +define('OFFLINE_IPINFO_DB_FILE', 'country_asn.mmdb'); require_once 'getIP_util.php'; -/** - * @param string $ip - * - * @return string|null - */ -function getLocalOrPrivateIpInfo($ip) -{ +function getLocalOrPrivateIpInfo($ip){ // ::1/128 is the only localhost ipv6 address. there are no others, no need to strpos this if ('::1' === $ip) { return 'localhost IPv6 access'; } - // simplified IPv6 link-local address (should match fe80::/10) if (stripos($ip, 'fe80:') === 0) { return 'link-local IPv6 access'; } - // fc00::/7 Unique Local IPv6 Unicast Addresses if (preg_match('/^(fc|fd)([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}$/i', $ip) === 1) { return 'ULA IPv6 access'; } - // anything within the 127/8 range is localhost ipv4, the ip must start with 127.0 if (strpos($ip, '127.') === 0) { return 'localhost IPv4 access'; } - // 10/8 private IPv4 if (strpos($ip, '10.') === 0) { return 'private IPv4 access'; } - // 172.16/12 private IPv4 if (preg_match('/^172\.(1[6-9]|2\d|3[01])\./', $ip) === 1) { return 'private IPv4 access'; } - // 192.168/16 private IPv4 if (strpos($ip, '192.168.') === 0) { return 'private IPv4 access'; } - // IPv4 link-local if (strpos($ip, '169.254.') === 0) { return 'link-local IPv4 access'; } - return null; } -/** - * @return string - */ -function getIpInfoTokenString() -{ - if ( - !file_exists(API_KEY_FILE) - || !is_readable(API_KEY_FILE) - ) { - return ''; +function getIspInfo_ipinfoApi($ip){ + if (!file_exists(API_KEY_FILE) || !is_readable(API_KEY_FILE)){ + return null; } - require API_KEY_FILE; - - if (empty($IPINFO_APIKEY)) { - return ''; + if(empty($IPINFO_APIKEY)){ + return null; } - - return '?token=' . $IPINFO_APIKEY; -} - -/** - * @param string $ip - * - * @return array|null - */ -function getIspInfo($ip) -{ - $json = file_get_contents('https://ipinfo.io/' . $ip . '/json' . getIpInfoTokenString()); + $json = file_get_contents('https://ipinfo.io/' . $ip . '/json?token=' . $IPINFO_APIKEY); if (!is_string($json)) { return null; } - $data = json_decode($json, true); if (!is_array($data)) { return null; } - - return $data; -} - -/** - * @param array|null $rawIspInfo - * - * @return string - */ -function getIsp($rawIspInfo) -{ - if (is_array($rawIspInfo)) { - /* variant with no token - has json like: - { - "ip": "xxx.xxx.xxx.xxx", - "hostname": "example.com", - "city": "Vienna", - "region": "Vienna", - "country": "AT", - "loc": "48.2085,16.3721", - "org": "ASxxxx T-Mobile Austria GmbH", - "postal": "nnnn", - "timezone": "Europe/Vienna", - "readme": "https://ipinfo.io/missingauth" + $isp=null; + //ISP name, if present, is either in org or asn.name + if (array_key_exists('org', $data) && is_string($data['org']) && !empty($data['org'])) { + // Remove AS##### from ISP name, if present + $isp = preg_replace('/AS\\d+\\s/', '', $data['org']); + } elseif (array_key_exists('asn', $data) && is_array($data['asn']) && !empty($data['asn']) && array_key_exists('name', $data['asn']) && is_string($data['asn']['name'])) { + $isp = $data['asn']['name']; + } else{ + return null; + } + $country=null; + if(array_key_exists('country',$data) && is_string($data['country'])){ + $country = $data['country']; + } + //If requested by the client (and we have the required information), calculate the distance + $distance=null; + if(isset($_GET['distance']) && ($_GET['distance']==='mi' || $_GET['distance']==='km') && array_key_exists('loc', $data) && is_string($data['loc'])){ + $unit = $_GET['distance']; + $clientLoc = $data['loc']; + $serverLoc = null; + if (file_exists(SERVER_LOCATION_CACHE_FILE) && is_readable(SERVER_LOCATION_CACHE_FILE)) { + require SERVER_LOCATION_CACHE_FILE; } - */ - if ( - array_key_exists('org', $rawIspInfo) - && is_string($rawIspInfo['org']) - && !empty($rawIspInfo['org']) - ) { - // Remove AS##### from ISP name, if present - return preg_replace('/AS\\d+\\s/', '', $rawIspInfo['org']); - } - - /* - variant with valid token has json: - { - "ip": "xxx.xxx.xxx.xxx", - "hostname": "example.com", - "city": "Vienna", - "region": "Vienna", - "country": "AT", - "loc": "48.2085,16.3721", - "postal": "1010", - "timezone": "Europe/Vienna", - "asn": { - "asn": "ASxxxx", - "name": "T-Mobile Austria GmbH", - "domain": "t-mobile.at", - "route": "xxx.xxx.xxx.xxx/xx", - "type": "isp" - }, - "company": { - "name": "XX", - "domain": "example.com", - "type": "isp" - }, - "privacy": { - "vpn": true, - "proxy": false, - "tor": false, - "relay": false, - "hosting": false, - "service": "" - }, - "abuse": { - "address": "...", - "country": "AT", - "email": "abuse@example.com", - "name": "XXX", - "network": "xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx", - "phone": "" - }, - "domains": { - "total": 0, - "domains": [ - - ] + if (!is_string($serverLoc) || empty($serverLoc)) { + $json = file_get_contents('https://ipinfo.io/json?token=' . $IPINFO_APIKEY); + if (!is_string($json)) { + return null; } + $sdata = json_decode($json, true); + if (!is_array($sdata) || !array_key_exists('loc', $sdata) || !is_string($sdata['loc']) || empty($sdata['loc'])) { + return null; } - */ - if ( - array_key_exists('asn', $rawIspInfo) - && is_array($rawIspInfo['asn']) - && !empty($rawIspInfo['asn']) - && array_key_exists('name', $rawIspInfo['asn']) - && is_string($rawIspInfo['asn']['name']) - ) { - // Remove AS##### from ISP name, if present - return $rawIspInfo['asn']['name']; + $serverLoc = $sdata['loc']; + file_put_contents(SERVER_LOCATION_CACHE_FILE, " $processedString, - 'rawIspInfo' => $rawIspInfo ?: '', + 'rawIspInfo' => $data ?: '', ]); } +if (PHP_MAJOR_VERSION >= 8){ + require_once("geoip2.phar"); +} +function getIspInfo_ipinfoOfflineDb($ip){ + if (!file_exists(OFFLINE_IPINFO_DB_FILE) || !is_readable(OFFLINE_IPINFO_DB_FILE)){ + return null; + } + $reader = new MaxMind\Db\Reader(OFFLINE_IPINFO_DB_FILE); + $data = $reader->get($ip); + if(!is_array($data)){ + return null; + } + $processedString = $ip.' - ' . $data['as_name'] . ', ' . $data['country_name']; + return json_encode([ + 'processedString' => $processedString, + 'rawIspInfo' => $data ?: '', + ]); +} + +function formatResponse_simple($ip,$ispName=null){ + $processedString=$ip; + if(is_string($ispName)){ + $processedString.=' - '.$ispName; + } + return json_encode([ + 'processedString' => $processedString, + 'rawIspInfo' => '', + ]); +} + +header('Content-Type: application/json; charset=utf-8'); +if (isset($_GET['cors'])) { + header('Access-Control-Allow-Origin: *'); + header('Access-Control-Allow-Methods: GET, POST'); +} +header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, s-maxage=0'); +header('Cache-Control: post-check=0, pre-check=0', false); +header('Pragma: no-cache'); + $ip = getClientIp(); - -$localIpInfo = getLocalOrPrivateIpInfo($ip); -// local ip, no need to fetch further information -if (is_string($localIpInfo)) { - sendResponse($ip, $localIpInfo); - exit; +//if the user requested the ISP info, we first try to fetch it using ipinfo.io (if there is no api key set it fails without sending data, it can also fail because of rate limiting or invalid responses), then we try with the offline db, if that also fails (or if ISP info was not requested) we just respond with the IP address +if(isset($_GET['isp'])){ + $localIpInfo = getLocalOrPrivateIpInfo($ip); + //local ip, no need to fetch further information + if (is_string($localIpInfo)) { + echo formatResponse_simple($ip,$localIpInfo); + }else{ + //ipinfo API and offline db require PHP 8 or newer + if (PHP_MAJOR_VERSION >= 8){ + $r=getIspInfo_ipinfoApi($ip); + if(!is_null($r)){ + echo $r; + }else{ + $r=getIspInfo_ipinfoOfflineDb($ip); + if(!is_null($r)){ + echo $r; + }else{ + echo formatResponse_simple($ip); + } + } + }else{ + echo formatResponse_simple($ip); + } + } +}else{ + echo formatResponse_simple($ip); } - -if (!isset($_GET['isp'])) { - sendResponse($ip); - exit; -} - -$rawIspInfo = getIspInfo($ip); -$isp = getIsp($rawIspInfo); -$distance = getDistance($rawIspInfo); - -sendResponse($ip, $isp, $distance, $rawIspInfo); diff --git a/html/backend/getIP_ipInfo_apikey.php b/html/backend/getIP_ipInfo_apikey.php deleted file mode 100644 index e200c3f..0000000 --- a/html/backend/getIP_ipInfo_apikey.php +++ /dev/null @@ -1,4 +0,0 @@ - - + - - - + + - - + - - - - + + Slackware UK: Speedtest - - + + - -

Slackware UK Logo

- -

Slackware UK Logo

- -

- is kindly sponsored by: -

- UK Servers Logo - - UK2 Logo +
+ -
- Please take a moment to visit the sponsors using the links above! -


-
- - - - -
- Slackware UK Speedtest

+
+
+ Patronage & Donations
+ If you use the Slackware UK services on a regular basis, and would like to contribute to running costs, make a continuing patronage (and receive special benefits), or make a one off PayPal payment, please use one of the following buttons: +
+ + Patreon Logo + PayPal Logo + + Patreon Logo + PayPal Logo + +
+ All donations will be gratefully received - thank you! +
+
+
+
+
+ Toggle theme:Toggle Theme Button +
+
+
+
+ Slackware UK Speedtest
+ On this page you can test the speed at which you
can download data from the Slackware UK server. -
-
-
-
-
-
Ping
-
-
ms
-
-
-
Jitter
-
-
ms
-
-
-
Download
-
-
Mbit/s
+
-
- Your IP information: +
+
+
+
Ping
+
+
ms
+
+
+
Jitter
+
+
ms
+
+
+
Download
+
+
Mbit/sec
+
+
+
+
+ Your IP information: +
+
+
Test progress
+
+
+
+ +
-
-
Test progress...
-
-
-
- diff --git a/html/init.js b/html/init.js deleted file mode 100644 index 5ca4410..0000000 --- a/html/init.js +++ /dev/null @@ -1,43 +0,0 @@ -var s=new Speedtest(); //create speedtest object - -s.setParameter("test_order","IP_D"); //we only want download test -s.setParameter("time_auto",true); //fixed duration for tests -s.setParameter("time_dl_max",10); //10 seconds for the download test - -s.onupdate=function(data){ - I("ip").textContent=data.clientIp; - I("dlText").textContent=(data.testState==1&&data.dlStatus==0)?"...":data.dlStatus; - I("pingText").textContent=data.pingStatus; - I("jitText").textContent=data.jitterStatus; - var prog=(Number(data.dlProgress)*2+Number(data.pingProgress))/3; - I("progress").style.width=(100*prog)+"%"; -} - -s.onend=function(aborted){ - I("startStopBtn").className=""; //show start button again - if(aborted){ - initUI(); - } -} - -function startStop(){ - if(s.getState()==3){ - //speedtest is running, abort - s.abort(); - }else{ - //test is not running, begin - s.start(); - I("startStopBtn").className="running"; - } -} - -function initUI(){ - I("dlText").textContent=""; - I("pingText").textContent=""; - I("jitText").textContent=""; - I("ip").textContent=""; -} - -function I(id){ - return document.getElementById(id); -} diff --git a/html/light.css b/html/light.css index f5ea8cc..ee2dbae 100644 --- a/html/light.css +++ b/html/light.css @@ -1,126 +1,235 @@ -body{ - text-align: center; +a:link { + color: #2c199c; + text-decoration: none; } -div.ip{ - color: #000000 !important; +a:visited { + color: #943cc3; + text-decoration: none; } -div.meterText:empty:before{ - color: #070707 !important; - content: "0.00"; +a:hover { + text-decoration: underline; } -div.meterText{ - position: absolute; - bottom: 1.5em; - left: 0; - width: 100%; - font-size: 2.5em; - z-index: 9; +body { + background-color: #ffffff; + background-image: url("/circuit-light.png"); + color: #000000; + padding-top: 15px; } -div.testArea{ - display: inline-block; - width: 20em; - height: 9em; - position: relative; - box-sizing: border-box; +hr { + background-color: #070707; + border: 0; + color: #070707; + height: 2px; } -div.progressText{ - margin-bottom: 2px; +img { + border: 0; +} + + +.bold { font-weight: bold; } -div.testGroup{ - display: inline-block; +.box { + background: #f0f0f0; + border: 2px solid #070707; + box-shadow: 10px 10px 10px -5px rgba(0,0,0,0.5); + overflow-x: auto; } -div.testName{ - position: absolute; - top: 0.1em; - left: 0; - width: 100%; - font-size: 1.4em; - color: #000000 !important; - z-index:9; +.boxmargins { + margin-bottom: 10px; } -div.unit{ - position: absolute; - bottom: 2em; - left: 0; - width: 100%; - color: #000000 !important; - z-index:9; +.boxpadding { + padding-bottom: 10px; + padding-left: 20px; + padding-right: 20px; + padding-top: 10px; } -html,body{ - border: none; - padding: 0; +.donatebutton { + margin-left: 100px; + margin-right: 100px; } -#dlText{ - color: #2c199c; +.heading { + font-size: 200%; } -#pingText,#jitText{ - color: #2c199c; +.metertext { + font-size: 200%; } -#progress{ - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 0%; - transition: width 2s; - background-color: #2c199c; +.metertext:empty:before { + content: "0.00"; } -#progressBar{ - width: 60%; - height: 0.3em; - background-color: #f0f0f0; - position: relative; +.notice { display: block; - margin: 0 auto; - border: 2px solid #000000; + margin-left: auto; + margin-bottom: 25px; + margin-right: auto; + text-align: center; + width: 70%; } -#startStopBtn{ - display: inline-block; - margin: 0 auto; - color: #2c199c; +.sponsor { + margin-top: 15px; + margin-bottom: 15px; +} + +.subheading { + font-size: 125%; +} + + +#copyright { + font-size: 10px; + text-align: center; +} + +#donatebuttons { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin-bottom: 10px; + margin-top: 20px; +} + +#headingbox { + margin-left: auto; + margin-right: auto; + width: fit-content; +} + +#headingtext { + margin-bottom: 5px; + margin-left: 5px; + margin-right: 5px; + margin-top: 5px; + text-align: center; +} + +#ipinfo { + text-align: center; +} + +#logo { + display: flex; + justify-content: center; + margin-bottom: 30px; +} + +#page { + margin-left: auto; + margin-right: auto; + width: 90%; +} + +#progress { + background-color: #2c199c; + height: 100%; + position: absolute; + transition: width 2s; + width: 0%; +} + +#progressbar { + background-color: #f0f0f0; + border: 2px solid #070707; + height: 8px; + margin-bottom: 5px; + margin-right: auto; + margin-left: auto; + position: relative; + width: 600px; +} + +#progresstext { + margin-bottom: 5px; + text-align: center; +} + +#startstopbutton { + #margin: 0 auto; background-color: #f0f0f0; border: 2px solid #2c199c; - /* border-radius: 0.3em; */ - transition: all 0.3s; box-sizing: border-box; - width: 8em; - height: 3em; - margin-bottom: 2em; - line-height: 2.7em; + color: #2c199c; cursor: pointer; - /* box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1); */ + height: 40px; + line-height: 36px; + transition: all 0.3s; + width: 150px; + margin-bottom: 30px; + margin-right: auto; + margin-left: auto; + text-align: center; } -#startStopBtn:before{ - content: "Start"; +#startstopbutton:before { + content: "Start Test"; } -#startStopBtn.running{ +#startstopbutton.running { background-color:#2c199c; - border-color:#000000; - color:#ffffff; + border-color:#070707; + color:#f0f0f0; } -#startStopBtn.running:before{ +#startstopbutton.running:before { content: "Abort"; } -#test{ - margin-top: 2em; - margin-bottom: 2em; +#testbox { + margin-left: auto; + margin-right: auto; + padding-left: 75px; + padding-right: 75px; + width: fit-content; +} + +#tests { + column-gap: 150px; + display: grid; + grid-template-columns: auto auto auto; + justify-content: center; + margin-bottom: 30px; + text-align: center; +} + +#theme { + column-gap: 50px; + display: grid; + grid-template-columns: auto auto auto; +} + +#themetoggle { + align-self: end; + display: flex; + height: 25px; + margin-left: auto; + margin-right: 0; + max-height: 25px; + text-align: right; +} + +#themetoggleimg { + height: 15px; + margin-right: 5px; + vertical-align: middle; +} + +#themetoggletext { + align-content: center; + color: #070707; + font-size: 15px; + margin-left: 5px; + margin-right: 5px; } diff --git a/html/patreon-black.png b/html/patreon-black.png new file mode 100644 index 0000000..d578abe Binary files /dev/null and b/html/patreon-black.png differ diff --git a/html/patreon-white.png b/html/patreon-white.png new file mode 100644 index 0000000..47c8649 Binary files /dev/null and b/html/patreon-white.png differ diff --git a/html/paypal-black.png b/html/paypal-black.png new file mode 100644 index 0000000..e0faea9 Binary files /dev/null and b/html/paypal-black.png differ diff --git a/html/paypal-white.png b/html/paypal-white.png new file mode 100644 index 0000000..0a31c88 Binary files /dev/null and b/html/paypal-white.png differ diff --git a/html/slackwareuk-black.png b/html/slackwareuk-black.png new file mode 100644 index 0000000..d3f8d1d Binary files /dev/null and b/html/slackwareuk-black.png differ diff --git a/html/slackwareuk-white.png b/html/slackwareuk-white.png new file mode 100644 index 0000000..9612f8f Binary files /dev/null and b/html/slackwareuk-white.png differ diff --git a/html/speedtest.js b/html/speedtest.js index 386fd22..f759c64 100644 --- a/html/speedtest.js +++ b/html/speedtest.js @@ -49,7 +49,7 @@ function Speedtest() { this._settings = {}; //settings for the speed test worker this._state = 0; //0=adding settings, 1=adding servers, 2=server selection done, 3=test running, 4=done console.log( - "LibreSpeed by Federico Dossena v5.3.1 - https://github.com/librespeed/speedtest" + "LibreSpeed by Federico Dossena v5.4 - https://github.com/librespeed/speedtest" ); } diff --git a/html/toggletheme.php b/html/toggletheme.php new file mode 100644 index 0000000..aedcbbb --- /dev/null +++ b/html/toggletheme.php @@ -0,0 +1,20 @@ + mktime (23, 59, 59, 12, 31, 2069), + "domain" => ".slackware.uk", + "path" => "/", + "httponly" => true, + "samesite" => "Lax" + ); + if ($_COOKIE['theme'] != "light") { + $theme = "light"; + } else { + $theme = "dark"; + } + setcookie ("theme", $theme, $cookie_data); + if (isset ($_SERVER['HTTP_REFERER'])) { + header ("Location: " . $_SERVER['HTTP_REFERER'], true, 302); + } else { + header ("Location: /", true, 302); + } +?> diff --git a/html/toggletheme.png b/html/toggletheme.png new file mode 100644 index 0000000..a4ba86f Binary files /dev/null and b/html/toggletheme.png differ diff --git a/html/ukservers.png b/html/ukservers.png new file mode 100644 index 0000000..d5df6ce Binary files /dev/null and b/html/ukservers.png differ