From a69a70f5f499b63f0c3475162c3c13c5ffd66444 Mon Sep 17 00:00:00 2001 From: Bernd Stellwag Date: Sat, 10 Oct 2020 07:08:17 +0200 Subject: [PATCH] Refactor backend PHP code (#362) * refactor getIP.php moving functionality into separate functions * add some error checks * remove closing php tags * uniformly use single quotes for strings most strings already used single quotes, some used double quotes * refactor garbage moving functionality into functions --- backend/empty.php | 16 +- backend/garbage.php | 72 ++++-- backend/getIP.php | 438 +++++++++++++++++++++++--------- backend/getIP_ipInfo_apikey.php | 5 +- 4 files changed, 376 insertions(+), 155 deletions(-) diff --git a/backend/empty.php b/backend/empty.php index e35f663..3c4547b 100644 --- a/backend/empty.php +++ b/backend/empty.php @@ -1,12 +1,14 @@ + +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'); +header('Connection: keep-alive'); diff --git a/backend/garbage.php b/backend/garbage.php index e2fcc78..89ab6c9 100644 --- a/backend/garbage.php +++ b/backend/garbage.php @@ -1,31 +1,63 @@ 1024) { + return 1024; + } + + return (int) $_GET['ckSize']; } -// Download follows... -header('Content-Description: File Transfer'); -header('Content-Type: application/octet-stream'); -header('Content-Disposition: attachment; filename=random.dat'); -header('Content-Transfer-Encoding: binary'); -// Never cache me -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'); + +/** + * @return void + */ +function sendHeaders() +{ + header('HTTP/1.1 200 OK'); + + if (isset($_GET['cors'])) { + header('Access-Control-Allow-Origin: *'); + header('Access-Control-Allow-Methods: GET, POST'); + } + + // Indicate a file download + header('Content-Description: File Transfer'); + header('Content-Type: application/octet-stream'); + header('Content-Disposition: attachment; filename=random.dat'); + header('Content-Transfer-Encoding: binary'); + + // Cache settings: never cache this request + 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'); +} + +// Determine how much data we should send +$chunks = getChunkCount(); + // Generate data -$data=openssl_random_pseudo_bytes(1048576); +$data = openssl_random_pseudo_bytes(1048576); + // Deliver chunks of 1048576 bytes -$chunks=isset($_GET['ckSize']) ? intval($_GET['ckSize']) : 4; -if(empty($chunks)){$chunks = 4;} -if($chunks>1024){$chunks = 1024;} -for($i=0;$i<$chunks;$i++){ +sendHeaders(); +for ($i = 0; $i < $chunks; $i++) { echo $data; flush(); } -?> diff --git a/backend/getIP.php b/backend/getIP.php index 7d7c400..136bb15 100644 --- a/backend/getIP.php +++ b/backend/getIP.php @@ -1,59 +1,171 @@ $ip . " - localhost IPv6 access", 'rawIspInfo' => ""]); - die(); + // simplified IPv6 link-local address (should match fe80::/10) + if (stripos($ip, 'fe80:') === 0) { + return 'link-local 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; } -if (stripos($ip, 'fe80:') === 0) { // simplified IPv6 link-local address (should match fe80::/10) - echo json_encode(['processedString' => $ip . " - link-local IPv6 access", 'rawIspInfo' => ""]); - die(); + +/** + * @return string + */ +function getIpInfoTokenString() +{ + if (!file_exists(API_KEY_FILE)) { + return ''; + } + + require API_KEY_FILE; + + if (empty($IPINFO_APIKEY)) { + return ''; + } + + return '?token='.$IPINFO_APIKEY; } -if (strpos($ip, '127.') === 0) { //anything within the 127/8 range is localhost ipv4, the ip must start with 127.0 - echo json_encode(['processedString' => $ip . " - localhost IPv4 access", 'rawIspInfo' => ""]); - die(); + +/** + * @param string $ip + * + * @return array|null + */ +function getIspInfo($ip) +{ + $json = file_get_contents('https://ipinfo.io/'.$ip.'/json'.getIpInfoTokenString()); + if (!is_string($json)) { + return null; + } + + $data = json_decode($json, true); + if (!is_array($data)) { + return null; + } + + return $data; } -if (strpos($ip, '10.') === 0) { // 10/8 private IPv4 - echo json_encode(['processedString' => $ip . " - private IPv4 access", 'rawIspInfo' => ""]); - die(); + +/** + * @param array|null $rawIspInfo + * + * @return string + */ +function getIsp($rawIspInfo) +{ + if ( + !is_array($rawIspInfo) + || !array_key_exists('org', $rawIspInfo) + || !is_string($rawIspInfo['org']) + || empty($rawIspInfo['org']) + ) { + return 'Unknown ISP'; + } + + // Remove AS##### from ISP name, if present + return preg_replace('/AS\\d+\\s/', '', $rawIspInfo['org']); } -if (preg_match('/^172\.(1[6-9]|2\d|3[01])\./', $ip) === 1) { // 172.16/12 private IPv4 - echo json_encode(['processedString' => $ip . " - private IPv4 access", 'rawIspInfo' => ""]); - die(); -} -if (strpos($ip, '192.168.') === 0) { // 192.168/16 private IPv4 - echo json_encode(['processedString' => $ip . " - private IPv4 access", 'rawIspInfo' => ""]); - die(); -} -if (strpos($ip, '169.254.') === 0) { // IPv4 link-local - echo json_encode(['processedString' => $ip . " - link-local IPv4 access", 'rawIspInfo' => ""]); - die(); + +/** + * @return string|null + */ +function getServerLocation() +{ + $serverLoc = null; + if (file_exists(SERVER_LOCATION_CACHE_FILE)) { + require SERVER_LOCATION_CACHE_FILE; + } + if (is_string($serverLoc) && !empty($serverLoc)) { + return $serverLoc; + } + + $json = file_get_contents('https://ipinfo.io/json'.getIpInfoTokenString()); + if (!is_string($json)) { + return null; + } + + $details = json_decode($json, true); + if ( + !is_array($details) + || !array_key_exists('loc', $details) + || !is_string($details['loc']) + || empty($details['loc']) + ) { + return null; + } + + $serverLoc = $details['loc']; + $cacheData = " $ip . " - " . $isp, 'rawIspInfo' => $rawIspInfo]); -} else { - echo json_encode(['processedString' => $ip, 'rawIspInfo' => ""]); + + $unit = $_GET['distance']; + $clientLocation = $rawIspInfo['loc']; + $serverLocation = getServerLocation(); + + if (!is_string($serverLocation)) { + return null; + } + + return calculateDistance( + $serverLocation, + $clientLocation, + $unit + ); } -?> + +/** + * @param string $clientLocation + * @param string $serverLocation + * @param string $unit + * + * @return string + */ +function calculateDistance($clientLocation, $serverLocation, $unit) +{ + list($clientLatitude, $clientLongitude) = explode(',', $clientLocation); + list($serverLatitude, $serverLongitude) = explode(',', $serverLocation); + $dist = distance( + $clientLatitude, + $clientLongitude, + $serverLatitude, + $serverLongitude + ); + + if ('mi' === $unit) { + $dist /= 1.609344; + $dist = round($dist, -1); + if ($dist < 15) { + $dist = '<15'; + } + + return $dist.' mi'; + } + + if ('km' === $unit) { + $dist = round($dist, -1); + if ($dist < 20) { + $dist = '<20'; + } + + return $dist.' km'; + } + + return null; +} + +/** + * @return void + */ +function sendHeaders() +{ + 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'); +} + +/** + * @param string $ip + * @param string|null $ipInfo + * @param string|null $distance + * @param array|null $rawIspInfo + * + * @return void + */ +function sendResponse( + $ip, + $ipInfo = null, + $distance = null, + $rawIspInfo = null +) { + $processedString = $ip; + if (is_string($ipInfo)) { + $processedString .= ' - '.$ipInfo; + } + + if ( + is_array($rawIspInfo) + && array_key_exists('country', $rawIspInfo) + ) { + $processedString .= ', '.$rawIspInfo['country']; + } + if (is_string($distance)) { + $processedString .= ' ('.$distance.')'; + } + + sendHeaders(); + echo json_encode([ + 'processedString' => $processedString, + 'rawIspInfo' => $rawIspInfo ?: '', + ]); +} + +$ip = getClientIp(); + +$localIpInfo = getLocalOrPrivateIpInfo($ip); +// local ip, no need to fetch further information +if (is_string($localIpInfo)) { + sendResponse($ip, $localIpInfo); + exit; +} + +if (!isset($_GET['isp'])) { + sendResponse($ip); + exit; +} + +$rawIspInfo = getIspInfo($ip); +$isp = getIsp($rawIspInfo); +$distance = getDistance($rawIspInfo); + +sendResponse($ip, $isp, $distance, $rawIspInfo); diff --git a/backend/getIP_ipInfo_apikey.php b/backend/getIP_ipInfo_apikey.php index 49da1dc..e200c3f 100644 --- a/backend/getIP_ipInfo_apikey.php +++ b/backend/getIP_ipInfo_apikey.php @@ -1,3 +1,4 @@ \ No newline at end of file + +// put your token between the quotes if you have one +$IPINFO_APIKEY = '';