diff --git a/public/assets/2021whois.js b/public/assets/2021whois.js new file mode 100644 index 0000000..0429029 --- /dev/null +++ b/public/assets/2021whois.js @@ -0,0 +1,98 @@ +(function() { + var locked = false, + input = document.getElementById('lookup-input'), + submit = document.getElementById('lookup-submit'), + result = document.getElementById('lookup-result'); + + var lock = function() { + if(locked) + return false; + + document.body.classList.add('whois-locked'); + input.disabled = true; + locked = true; + return true; + } + + var unlock = function() { + if(!locked) + return false; + + document.body.classList.remove('whois-locked'); + input.disabled = false; + locked = false; + return true; + } + + var lookup = function(target) { + if(!lock()) + return; + + var xhr = new XMLHttpRequest; + xhr.addEventListener('load', function() { + var resp = JSON.parse(xhr.responseText); + + if(resp.error) { + alert(resp.text); + } else { + var lastWhois = resp.result.responses[resp.result.responses.length - 1], + isIpAddr = false; + + for(var i = 0; i < lastWhois.lines.length; ++i) { + var line = lastWhois.lines[i]; + if(line.substring(0, 4) === 'inet') { + isIpAddr = true; + break; + } + } + + var text = ''; + + if(isIpAddr) { + text += 'RESULTS FOUND: ' + resp.result.responses.length.toString() + "\r\n"; + for(var i = 0; i < resp.result.responses.length; ++i) { + var response = resp.result.responses[i]; + text += "\r\n-------------\r\n"; + text += 'Lookup results for ' + resp.result.target + ' from ' + response.server + ":\r\n\r\n"; + text += response.lines.join("\r\n").trim() + "\r\n"; + } + } else { + for(var i = 0; i < resp.result.responses.length; ++i) { + var response = resp.result.responses[i]; + text += resp.result.target + ' domain lookup result from ' + response.server + "\r\n\r\n"; + text += response.lines.join("\r\n").trim() + "\r\n\r\n"; + } + } + + result.textContent = text; + } + + unlock(); + }); + xhr.open('GET', '/whois/lookup?target=' + encodeURIComponent(target)); + xhr.send(); + } + + var readHash = function() { + if(location.hash.length < 2) { + result.textContent = 'Enter a domain or IP address!'; + return; + } + + var target = decodeURIComponent(location.hash.substring(1)); + if(input.value !== target) + input.value = target; + lookup(target); + }; + + window.addEventListener('hashchange', function(ev) { + readHash(); + }, false); + + submit.addEventListener('click', function(ev) { + ev.preventDefault(); + location.hash = encodeURIComponent(input.value); + }); + + readHash(); +})(); diff --git a/public/css/2021.css b/public/css/2021.css index c994cec..0e41c91 100644 --- a/public/css/2021.css +++ b/public/css/2021.css @@ -1121,3 +1121,64 @@ body { max-width: 1200px; margin: 0 auto; } + +.whois-container { + max-width: 1200px; + margin: 0 auto; +} + +.whois-lookup-form { + display: flex; + border-radius: 5px; + margin: 10px; + overflow: hidden; + box-shadow: 0 1px 5px #222; + transition: opacity .2s; +} +.whois-locked .whois-lookup-form { + opacity: .5; +} +.whois-lookup-form-input { + display: block; + flex: 1 1 auto; + padding: 10px; + background-color: #212121; + background-image: linear-gradient(0deg, #262626, #202020); + border-width: 0; + color: #fff; + font-family: Tahoma, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif; +} +.whois-lookup-form-submit { + flex: 0 0 auto; + background-color: #333333; + background-image: linear-gradient(0deg, transparent, #404040); + color: #fff; + border-width: 0; + padding: 10px; + cursor: pointer; + border-radius: 0; + transition: background-color .2s; +} +.whois-lookup-form-submit:focus, +.whois-lookup-form-submit:hover { + background-color: #3F3F3F; +} +.whois-lookup-form-submit:active { + background-color: #393939; +} + +.whois-result { + margin: 10px; + padding: 6px 10px; + white-space: pre-wrap; + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 14px; + transition: opacity .2s; + background-color: #202020; + border-radius: 5px; + box-shadow: 0 1px 5px #222; + overflow: auto; +} +.whois-locked .whois-result { + opacity: .5; +} diff --git a/public/index.php b/public/index.php index dfee66a..c7d7c0d 100644 --- a/public/index.php +++ b/public/index.php @@ -269,5 +269,49 @@ $router->get('/git_keys_rw', function() use ($db) { return $body; }); +$router->get('/whois', function() use ($ctx) { + return $ctx->getTemplating()->render('whois'); +}); + +$router->get('/whois/lookup', function($response, $request) use ($ctx) { + $target = trim((string)$request->getParam('target')); + if(empty($target)) + return [ + 'error' => true, + 'text' => 'Missing input data.', + ]; + + $hash = hash('sha256', $target); + $prefix = 'fm:whois2:target:'; + $source = ''; + + try { + $redis = new \Redis; + $redis->connect('/var/run/redis/redis-server.sock'); + + $result = $redis->get($prefix . $hash); + + if(empty($result)) { + $client = new \Makai\Whois\WhoisClient; + $result = $client->lookup($target); + $redis->setEx($prefix . $hash, 1800, serialize($result)); + $source = 'fresh'; + } else { + $result = unserialize($result); + $source = 'cache'; + } + } catch (\RuntimeException $ex) { + return [ + 'error' => true, + 'text' => $ex->getMessage(), + ]; + } + + return [ + 'error' => false, + 'source' => $source, + 'result' => $result, + ]; +}); $router->dispatch(); diff --git a/public/whois/index.php b/public/whois/index.php deleted file mode 100644 index 2751f1f..0000000 --- a/public/whois/index.php +++ /dev/null @@ -1,110 +0,0 @@ -connect('/var/run/redis/redis-server.sock'); - - $result = $redis->get(FMWHOIS_PREFIX . $domainHash); - - if(empty($result)) { - $whois = new Whois\Client; - - try { - $result = $whois->lookup($domain); - $redis->setEx(FMWHOIS_PREFIX . $domainHash, 1800, json_encode($result)); - } catch (Whois\WhoisException $ex) { - $error = $ex->getMessage(); - } - } else { - $result = json_decode($result); - } -} - -if(!empty($error)) { - $responseText = $error; -} elseif(!empty($result)) { - $responseText = ''; - - switch($result->type) { - case 'domain': - foreach($result->responses as $server => $response) { - $responseText .= "{$result->target} domain lookup results from {$server}\r\n\r\n"; - $responseText .= trim($response) . "\r\n"; - } - break; - - case 'ip': - $responseText .= "RESULTS FOUND: " . count($result->responses); - - foreach($result->responses as $server => $response) { - $responseText .= "-------------\r\n"; - $responseText .= "Lookup results for {$result->target} from {$server}:\r\n\r\n"; - $responseText .= trim($response) . "\r\n"; - } - break; - - default: - $responseText .= 'Something happened.'; - break; - } -} else { - $responseText = 'Enter a domain or IP address!'; -} - -if(isset($_GET['ajax'])) { - header('Content-Type: application/json; charset=utf-8'); - - if(!is_object($result)) - $result = new stdClass; - - $result->responseText = $responseText; - die(json_encode($result)); -} -?> - - - - - flash.moe whois - - - - -
-
-
flash.moe whois
- -
- -
- - -
- -
- -
- © flashwave 2013- -
-
- - - - diff --git a/public/whois/script.js b/public/whois/script.js deleted file mode 100644 index b5c7b8a..0000000 --- a/public/whois/script.js +++ /dev/null @@ -1,54 +0,0 @@ -var documentLocked = false; - -window.addEventListener('load', function() { - document.getElementById('lookup-submit').addEventListener('click', function(ev) { - ev.preventDefault(); - whoisLookup(document.getElementById('lookup-input').value); - }); -}); - -window.addEventListener('popstate', function(ev) { - if(!ev.state) - return; - document.getElementById('lookup-input').value = ev.state.target || ''; - document.getElementById('lookup-result').innerText = ev.state.responseText || 'Enter a domain or IP address!'; -}); - -function lockDocument() { - if(documentLocked) - return false; - - document.body.classList.add('locked'); - document.getElementById('lookup-input').disabled = true; - documentLocked = true; - return true; -} - -function freeDocument() { - if(!documentLocked) - return false; - - document.body.classList.remove('locked'); - document.getElementById('lookup-input').disabled = false; - documentLocked = false; - return true; -} - -function whoisLookup(domain) { - if(!lockDocument()) - return; - - var xhr = new XMLHttpRequest; - xhr.addEventListener('readystatechange', function() { - if(xhr.readyState != 4) - return; - - var response = JSON.parse(xhr.responseText); - - history.pushState(response, null, location.pathname + '?domain=' + encodeURIComponent(domain)); - document.getElementById('lookup-result').innerText = response.responseText; - freeDocument(); - }); - xhr.open('GET', whoisUrl + '?ajax=1&domain=' + encodeURIComponent(domain)); - xhr.send(); -} diff --git a/public/whois/style.css b/public/whois/style.css deleted file mode 100644 index 2499770..0000000 --- a/public/whois/style.css +++ /dev/null @@ -1,129 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; - position: relative; - outline-style: none; - scrollbar-color: #4a3650 #111; -} - -html, -body { - width: 100%; - height: 100%; -} - -body { - font-family: Tahoma, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif; - font-size: 12px; - line-height: 20px; - background-color: #111; - color: #fff; - padding: 1px; -} - -.container { - max-width: 1020px; - margin: 0 auto; -} - -.header { - display: flex; - justify-content: space-between; - margin: 10px; -} -.title { - font-size: 20px; - line-height: 25px; -} -.nav { - display: flex; - font-size: 16px; - line-height: 25px; -} -.nav a { - color: #ccc; - text-decoration: none; - padding: 2px 5px; - transition: color .2s, text-shadow .2s; -} -.nav a:hover, -.nav a:focus { - color: #fff; - text-shadow: 0 0 10px #fcfcfc; -} -.nav a:active { - color: #ddd; - text-shadow: 0 0 6px #fcfcfc; -} - -.lookup-form { - display: flex; - border-radius: 5px; - margin: 10px; - overflow: hidden; - box-shadow: 0 1px 5px #222; - transition: opacity .2s; -} -.locked .lookup-form { - opacity: .5; -} -.lookup-form-input { - display: block; - flex: 1 1 auto; - padding: 10px; - background-color: #212121; - background-image: linear-gradient(0deg, #262626, #202020); - border-width: 0; - color: #fff; - font-family: Tahoma, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif; -} -.lookup-form-submit { - flex: 0 0 auto; - background-color: #333333; - background-image: linear-gradient(0deg, transparent, #404040); - color: #fff; - border-width: 0; - padding: 10px; - cursor: pointer; - border-radius: 0; - transition: background-color .2s; -} -.lookup-form-submit:focus, -.lookup-form-submit:hover { - background-color: #3F3F3F; -} -.lookup-form-submit:active { - background-color: #393939; -} - -.result { - margin: 10px; - padding: 6px 10px; - white-space: pre-wrap; - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 14px; - transition: opacity .2s; - background-color: #202020; - border-radius: 5px; - box-shadow: 0 1px 5px #222; - overflow: auto; -} -.locked .result { - opacity: .5; -} - -.copy { - font-size: 11px; - line-height: 16px; - text-align: center; - margin: 10px; -} -.copy a { - color: inherit; - text-decoration: none; -} -.copy a:hover, -.copy a:focus { - text-decoration: underline; -} diff --git a/public/whois/whois-php/src/Whois/Client.php b/public/whois/whois-php/src/Whois/Client.php deleted file mode 100644 index 92bd951..0000000 --- a/public/whois/whois-php/src/Whois/Client.php +++ /dev/null @@ -1,234 +0,0 @@ -servers = new $servers; - } - - /** - * Loop up a target (ip/domain) on whois - * - * @param string $target The target domain/ip. - * - * @throws WhoisException if the given target doesn't validate as an IP or domain. - * - * @return Result The response from the whois server - */ - public function lookup($target) - { - // Check if IP - if (filter_var($target, FILTER_VALIDATE_IP)) { - return $this->lookupIP($target); - } - - // Check if domain - if ($this->verifyDomainName($target)) { - return $this->lookupDomain($target); - } - - // Throw an error if both are false - throw new WhoisException('The target supplied does not appear to be a valid IP or domain name.'); - } - - private function lookupDomain($target) - { - // Make target completely lowercase - $target = strtolower($target); - - // Split the dots - $targetSplit = explode('.', $target); - - // Create server variable - $server = null; - - // Select a server - while (count($targetSplit)) { - // Glue array - $tld = implode('.', $targetSplit); - - // Check if it exists in the tld servers variable - if (array_key_exists($tld, $this->servers->tld)) { - $server = $this->servers->tld[$tld]; - break; - } - - // Remove first entry - array_shift($targetSplit); - } - - // If we get here and $server is still null throw an exception - if ($server === null) { - throw new WhoisException('No whois server found for this domain.'); - } - - // Create a Result object - $result = new Result(); - - // Set the domain - $result->target = $target; - - // Set the type - $result->type = 'domain'; - - // Create responses container - $responses = []; - - // Query the server - $response = $this->query($target, $server); - - // Process the data if anything was returned - if ($response) { - // Add the response to the array - $responses[$server] = $response; - - // Check if there's a secondary whois server - if ($position = strpos(strtolower($response), 'whois server:')) { - // Grab the uri from the response - preg_match("/whois server: (.*)/", strtolower($response), $matches); - - // Check if it's not the same server - if (isset($matches[1]) && trim(strtolower($server)) !== trim($matches[1]) && strpos($matches[1], ':') === false) { - // Set the secondary server - $second = trim($matches[1]); - - // Do a query - $response = $this->query($target, $second); - - // Check if that was something - if ($response) { - // Add it to the responses - $responses[$second] = $response; - } - } - } - } - - // Set the count - $result->count = count($responses); - - // Set the responses - $result->responses = array_reverse($responses); - - // Return the result - return $result; - } - - /** - * Whois an IP address. - * - * @param string $address The IP address to query. - * - * @return Result The whois results. - */ - private function lookupIP($address) - { - // Create the responses storage array - $responses = []; - - // Query every server in the IP list - foreach ($this->servers->ip as $server) { - // Check if we haven't queried this server yet - if (array_key_exists($server, $responses)) { - continue; - } - - // Query the server - $responses[$server] = $this->query($address, $server); - } - - // Create a result object - $result = new Result(); - - // Set target - $result->target = $address; - - // Set the type - $result->type = 'ip'; - - // Set response count - $result->count = count($responses); - - // Set responses - $result->responses = array_reverse($responses); - - // Return the Result object - return $result; - } - - /** - * Validates a domain name. - * - * @param string $domain The string to validate as a domain. - * - * @return bool will be positive if the string is a domain. - */ - private function verifyDomainName($domain) - { - return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain) // Valid chars check - && preg_match("/^.{1,253}$/", $domain) // Overall length check - && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain)); // Length of each label - } - - /** - * Query the whois server. - * - * @param string $target The target IP/domain. - * @param string $server The server to be queried. - * @param int $port The port for the whois server. - * @param int $timeout The timeout. - * - * @throws WhoisException if the socket failed to open. - * - * @return string The response from the whois server. - */ - private function query($target, $server, $port = 43, $timeout = 5) - { - // Create the socket - $sock = @fsockopen($server, $port, $errno, $errstr, $timeout); - - // Check for errors - if (!$sock) { - // Throw an exception with the error string - throw new WhoisException($errstr); - } - - // Write the target to the socket - fwrite($sock, $target . "\r\n"); - - // Create storage variable - $response = ''; - - // Await output - while ($line = fgets($sock)) { - $response .= $line; - } - - // Close the socket - fclose($sock); - - // Return the response - return $response; - } -} diff --git a/public/whois/whois-php/src/Whois/Result.php b/public/whois/whois-php/src/Whois/Result.php deleted file mode 100644 index 3035805..0000000 --- a/public/whois/whois-php/src/Whois/Result.php +++ /dev/null @@ -1,34 +0,0 @@ - 'whois.nic.ac', - 'ac' => 'whois.nic.ac', - 'academy' => 'whois.donuts.co', - 'accountants' => 'whois.donuts.co', - 'active' => 'whois.afilias-srs.net', - 'actor' => 'whois.unitedtld.com', - 'actor' => 'whois.unitedtld.com', - 'ad' => 'whois.ripe.net', - 'ae' => 'whois.nic.ae', - 'aero' => 'whois.aero', - 'af' => 'whois.nic.af', - 'ag' => 'whois.nic.ag', - 'agency' => 'whois.donuts.co', - 'ai' => 'whois.ai', - 'airforce' => 'whois.unitedtld.com', - 'al' => 'whois.ripe.net', - 'allfinanz' => 'whois.ksregistry.net', - 'alsace' => 'whois-alsace.nic.fr', - 'am' => 'whois.amnic.net', - 'army' => 'whois.rightside.co', - 'arpa' => 'whois.iana.org', - 'as' => 'whois.nic.as', - 'asia' => 'whois.nic.asia', - 'associates' => 'whois.donuts.co', - 'at' => 'whois.nic.at', - 'attorney' => 'whois.rightside.co', - 'au' => 'whois.audns.net.au', - 'auction' => 'whois.unitedtld.com', - 'audio' => 'whois.uniregistry.net', - 'autos' => 'whois.afilias-srs.net', - 'aw' => 'whois.nic.aw', - 'ax' => 'whois.ax', - 'az' => 'whois.ripe.net', - 'band' => 'whois.rightside.co', - 'bar' => 'whois.nic.bar', - 'bargains' => 'whois.donuts.co', - 'bayern' => 'whois-dub.mm-registry.com', - 'be' => 'whois.dns.be', - 'beer' => 'whois-dub.mm-registry.com', - 'berlin' => 'whois.nic.berlin', - 'best' => 'whois.nic.best', - 'bg' => 'whois.register.bg', - 'bi' => 'whois.nic.bi', - 'bike' => 'whois.donuts.co', - 'bio' => 'whois.ksregistry.net', - 'biz' => 'whois.biz', - 'bj' => 'whois.nic.bj', - 'black' => 'whois.afilias.net', - 'blackfriday' => 'whois.uniregistry.net', - 'blue' => 'whois.afilias.net', - 'bmw' => 'whois.ksregistry.net', - 'bn' => 'whois.bn', - 'bnpparibas' => 'whois.afilias-srs.net', - 'bo' => 'whois.nic.bo', - 'boo' => 'domain-registry-whois.l.google.com', - 'boutique' => 'whois.donuts.co', - 'br' => 'whois.nic.br', - 'brussels' => 'whois.nic.brussels', - 'bt' => 'whois.netnames.net', - 'budapest' => 'whois-dub.mm-registry.com', - 'build' => 'whois.nic.build', - 'builders' => 'whois.donuts.co', - 'business' => 'whois.donuts.co', - 'business' => 'whois.donuts.co', - 'bw' => 'whois.nic.net.bw', - 'by' => 'whois.cctld.by', - 'bz' => 'whois.belizenic.bz', - 'bzh' => 'whois-bzh.nic.fr', - 'ca' => 'whois.cira.ca', - 'cab' => 'whois.donuts.co', - 'cal' => 'domain-registry-whois.l.google.com', - 'camera' => 'whois.donuts.co', - 'camp' => 'whois.donuts.co', - 'cancerresearch' => 'whois.nic.cancerresearch', - 'capetown' => 'capetown-whois.registry.net.za', - 'capital' => 'whois.donuts.co', - 'cards' => 'whois.donuts.co', - 'care' => 'whois.donuts.co', - 'career' => 'whois.nic.career', - 'careers' => 'whois.donuts.co', - 'casa' => 'whois-dub.mm-registry.com', - 'cash' => 'whois.donuts.co', - 'cat' => 'whois.cat', - 'catering' => 'whois.donuts.co', - 'cc' => 'ccwhois.verisign-grs.com', - 'cd' => 'whois.nic.cd', - 'center' => 'whois.donuts.co', - 'ceo' => 'whois.nic.ceo', - 'cern' => 'whois.afilias-srs.net', - 'cf' => 'whois.dot.cf', - 'ch' => 'whois.nic.ch', - 'channel' => 'domain-registry-whois.l.google.com', - 'cheap' => 'whois.donuts.co', - 'christmas' => 'whois.uniregistry.net', - 'chrome' => 'domain-registry-whois.l.google.com', - 'church' => 'whois.donuts.co', - 'ci' => 'whois.nic.ci', - 'city' => 'whois.donuts.co', - 'ck' => 'whois.nic.ck', - 'cl' => 'whois.nic.cl', - 'claims' => 'whois.donuts.co', - 'cleaning' => 'whois.donuts.co', - 'click' => 'whois.uniregistry.net', - 'clinic' => 'whois.donuts.co', - 'clothing' => 'whois.donuts.co', - 'club' => 'whois.nic.club', - 'cn' => 'whois.cnnic.net.cn', - 'co' => 'whois.co', - 'codes' => 'whois.donuts.co', - 'coffee' => 'whois.donuts.co', - 'college' => 'whois.centralnic.com', - 'cologne' => 'whois-fe1.pdt.cologne.tango.knipp.de', - 'com' => 'whois.verisign-grs.com', - 'community' => 'whois.donuts.co', - 'company' => 'whois.donuts.co', - 'computer' => 'whois.donuts.co', - 'condos' => 'whois.donuts.co', - 'construction' => 'whois.donuts.co', - 'consulting' => 'whois.unitedtld.com', - 'contractors' => 'whois.donuts.co', - 'cooking' => 'whois-dub.mm-registry.com', - 'cool' => 'whois.donuts.co', - 'coop' => 'whois.nic.coop', - 'country' => 'whois-dub.mm-registry.com', - 'credit' => 'whois.donuts.co', - 'creditcard' => 'whois.donuts.co', - 'cruises' => 'whois.donuts.co', - 'cuisinella' => 'whois.nic.cuisinella', - 'cx' => 'whois.nic.cx', - 'cymru' => 'whois.nic.cymru', - 'cz' => 'whois.nic.cz', - 'dad' => 'domain-registry-whois.l.google.com', - 'dance' => 'whois.unitedtld.com', - 'dating' => 'whois.donuts.co', - 'day' => 'domain-registry-whois.l.google.com', - 'de' => 'whois.denic.de', - 'deals' => 'whois.donuts.co', - 'democrat' => 'whois.rightside.co', - 'degree' => 'whois.unitedtld.com', - 'dental' => 'whois.donuts.co', - 'dentist' => 'whois.rightside.co', - 'desi' => 'whois.ksregistry.net', - 'diamonds' => 'whois.donuts.co', - 'diet' => 'whois.uniregistry.net', - 'digital' => 'whois.donuts.co', - 'direct' => 'whois.donuts.co', - 'directory' => 'whois.donuts.co', - 'discount' => 'whois.donuts.co', - 'dk' => 'whois.dk-hostmaster.dk', - 'dm' => 'whois.nic.dm', - 'domains' => 'whois.donuts.co', - 'durban' => 'durban-whois.registry.net.za', - 'dvag' => 'whois.ksregistry.net', - 'dz' => 'whois.nic.dz', - 'eat' => 'domain-registry-whois.l.google.com', - 'ec' => 'whois.nic.ec', - 'edu' => 'whois.educause.edu', - 'education' => 'whois.donuts.co', - 'ee' => 'whois.eenet.ee', - 'eg' => 'whois.ripe.net', - 'email' => 'whois.donuts.co', - 'engineer' => 'whois.rightside.co', - 'engineering' => 'whois.donuts.co', - 'enterprises' => 'whois.donuts.co', - 'equipment' => 'whois.donuts.co', - 'es' => 'whois.nic.es', - 'esq' => 'domain-registry-whois.l.google.com', - 'estate' => 'whois.donuts.co', - 'eu' => 'whois.eu', - 'eus' => 'whois.eus.coreregistry.net', - 'events' => 'whois.donuts.co', - 'exchange' => 'whois.donuts.co', - 'expert' => 'whois.donuts.co', - 'exposed' => 'whois.donuts.co', - 'fail' => 'whois.donuts.co', - 'farm' => 'whois.donuts.co', - 'feedback' => 'whois.centralnic.com', - 'fi' => 'whois.ficora.fi', - 'finance' => 'whois.donuts.co', - 'financial' => 'whois.donuts.co', - 'fish' => 'whois.donuts.co', - 'fishing' => 'whois-dub.mm-registry.com', - 'fitness' => 'whois.donuts.co', - 'flights' => 'whois.donuts.co', - 'florist' => 'whois.donuts.co', - 'flsmidth' => 'whois.ksregistry.net', - 'fly' => 'domain-registry-whois.l.google.com', - 'fo' => 'whois.nic.fo', - 'foo' => 'domain-registry-whois.l.google.com', - 'forsale' => 'whois.unitedtld.com', - 'foundation' => 'whois.donuts.co', - 'fr' => 'whois.nic.fr', - 'frl' => 'whois.nic.frl', - 'frogans' => 'whois-frogans.nic.fr', - 'fund' => 'whois.donuts.co', - 'furniture' => 'whois.donuts.co', - 'futbol' => 'whois.unitedtld.com', - 'gal' => 'whois.gal.coreregistry.net', - 'gallery' => 'whois.donuts.co', - 'gbiz' => 'domain-registry-whois.l.google.com', - 'gd' => 'whois.nic.gd', - 'gent' => 'whois.nic.gent', - 'gg' => 'whois.channelisles.net', - 'gi' => 'whois2.afilias-grs.net', - 'gift' => 'whois.uniregistry.net', - 'gifts' => 'whois.donuts.co', - 'gives' => 'whois.rightside.co', - 'gl' => 'whois.nic.gl', - 'glass' => 'whois.donuts.co', - 'gle' => 'domain-registry-whois.l.google.com', - 'global' => 'whois.afilias-srs.net', - 'globo' => 'whois.gtlds.nic.br', - 'gmail' => 'domain-registry-whois.l.google.com', - 'gmx' => 'whois-fe1.gmx.tango.knipp.de', - 'google' => 'domain-registry-whois.l.google.com', - 'gop' => 'whois-cl01.mm-registry.com', - 'gov' => 'whois.nic.gov', - 'gq' => 'whois.dominio.gq', - 'gr' => 'whois.ripe.net', - 'gratis' => 'whois.donuts.co', - 'green' => 'whois.afilias.net', - 'gripe' => 'whois.donuts.co', - 'gs' => 'whois.nic.gs', - 'guide' => 'whois.donuts.co', - 'guitars' => 'whois.uniregistry.net', - 'guru' => 'whois.donuts.co', - 'gy' => 'whois.registry.gy', - 'hamburg' => 'whois.nic.hamburg', - 'haus' => 'whois.unitedtld.com', - 'healthcare' => 'whois.donuts.co', - 'help' => 'whois.uniregistry.net', - 'here' => 'domain-registry-whois.l.google.com', - 'hiphop' => 'whois.uniregistry.net', - 'hiv' => 'whois.afilias-srs.net', - 'hk' => 'whois.hkirc.hk', - 'hn' => 'whois.nic.hn', - 'holdings' => 'whois.donuts.co', - 'holiday' => 'whois.donuts.co', - 'homes' => 'whois.afilias-srs.net', - 'horse' => 'whois-dub.mm-registry.com', - 'host' => 'whois.nic.host', - 'hosting' => 'whois.uniregistry.net', - 'house' => 'whois.donuts.co', - 'how' => 'domain-registry-whois.l.google.com', - 'hr' => 'whois.dns.hr', - 'ht' => 'whois.nic.ht', - 'hu' => 'whois.nic.hu', - 'ibm' => 'whois.nic.ibm', - 'id' => 'whois.pandi.or.id', - 'ie' => 'whois.domainregistry.ie', - 'il' => 'whois.isoc.org.il', - 'im' => 'whois.nic.im', - 'immo' => 'whois.donuts.co', - 'immobilien' => 'whois.unitedtld.com', - 'in' => 'whois.inregistry.net', - 'industries' => 'whois.donuts.co', - 'info' => 'whois.afilias.net', - 'ing' => 'domain-registry-whois.l.google.com', - 'ink' => 'whois.centralnic.com', - 'institute' => 'whois.donuts.co', - 'insure' => 'whois.donuts.co', - 'int' => 'whois.iana.org', - 'international' => 'whois.donuts.co', - 'investments' => 'whois.donuts.co', - 'io' => 'whois.nic.io', - 'iq' => 'whois.cmc.iq', - 'ir' => 'whois.nic.ir', - 'is' => 'whois.isnic.is', - 'it' => 'whois.nic.it', - 'je' => 'whois.channelisles.net', - 'jobs' => 'jobswhois.verisign-grs.com', - 'joburg' => 'joburg-whois.registry.net.za', - 'jp' => 'whois.jprs.jp', - 'juegos' => 'whois.uniregistry.net', - 'kaufen' => 'whois.unitedtld.com', - 'ke' => 'whois.kenic.or.ke', - 'kg' => 'www.domain.kg', - 'ki' => 'whois.nic.ki', - 'kim' => 'whois.afilias.net', - 'kitchen' => 'whois.donuts.co', - 'kiwi' => 'whois.nic.kiwi', - 'koeln' => 'whois-fe1.pdt.koeln.tango.knipp.de', - 'kr' => 'whois.kr', - 'krd' => 'whois.aridnrs.net.au', - 'kz' => 'whois.nic.kz', - 'la' => 'whois.nic.la', - 'lacaixa' => 'whois.nic.lacaixa', - 'land' => 'whois.donuts.co', - 'lawyer' => 'whois.rightside.co', - 'lease' => 'whois.donuts.co', - 'lgbt' => 'whois.afilias.net', - 'li' => 'whois.nic.li', - 'life' => 'whois.donuts.co', - 'lighting' => 'whois.donuts.co', - 'limited' => 'whois.donuts.co', - 'limo' => 'whois.donuts.co', - 'link' => 'whois.uniregistry.net', - 'loans' => 'whois.donuts.co', - 'london' => 'whois-lon.mm-registry.com', - 'lotto' => 'whois.afilias.net', - 'love' => 'whois.nic.love', - 'lt' => 'whois.domreg.lt', - 'ltda' => 'whois.afilias-srs.net', - 'lu' => 'whois.dns.lu', - 'luxe' => 'whois-dub.mm-registry.com', - 'luxury' => 'whois.nic.luxury', - 'lv' => 'whois.nic.lv', - 'ly' => 'whois.nic.ly', - 'ma' => 'whois.iam.net.ma', - 'maison' => 'whois.donuts.co', - 'management' => 'whois.donuts.co', - 'mango' => 'whois.mango.coreregistry.net', - 'market' => 'whois.rightside.co', - 'marketing' => 'whois.donuts.co', - 'md' => 'whois.nic.md', - 'me' => 'whois.nic.me', - 'media' => 'whois.donuts.co', - 'meet' => 'whois.afilias.net', - 'melbourne' => 'whois.aridnrs.net.au', - 'meme' => 'domain-registry-whois.l.google.com', - 'menu' => 'whois.nic.menu', - 'mg' => 'whois.nic.mg', - 'miami' => 'whois-dub.mm-registry.com', - 'mil' => 'whois.internic.net', - 'mini' => 'whois.ksregistry.net', - 'mk' => 'whois.marnet.mk', - 'ml' => 'whois.dot.ml', - 'mn' => 'whois.nic.mn', - 'mo' => 'whois.monic.mo', - 'mobi' => 'whois.dotmobiregistry.net', - 'moda' => 'whois.unitedtld.com', - 'moe' => 'whois.nic.moe', - 'monash' => 'whois.nic.monash', - 'mortgage' => 'whois.rightside.co', - 'moscow' => 'whois.nic.moscow', - 'motorcycles' => 'whois.afilias-srs.net', - 'mov' => 'domain-registry-whois.l.google.com', - 'mp' => 'whois.nic.mp', - 'ms' => 'whois.nic.ms', - 'mu' => 'whois.nic.mu', - 'museum' => 'whois.museum', - 'mx' => 'whois.mx', - 'my' => 'whois.mynic.my', - 'mz' => 'whois.nic.mz', - 'na' => 'whois.na-nic.com.na', - 'name' => 'whois.nic.name', - 'navy' => 'whois.rightside.co', - 'nc' => 'whois.nc', - 'net' => 'whois.verisign-grs.net', - 'network' => 'whois.donuts.co', - 'new' => 'domain-registry-whois.l.google.com', - 'nexus' => 'domain-registry-whois.l.google.com', - 'nf' => 'whois.nic.nf', - 'ng' => 'whois.nic.net.ng', - 'ngo' => 'whois.publicinterestregistry.net', - 'ninja' => 'whois.unitedtld.com', - 'nl' => 'whois.domain-registry.nl', - 'no' => 'whois.norid.no', - 'nra' => 'whois.afilias-srs.net', - 'nrw' => 'whois.nic.nrw', - 'nu' => 'whois.nic.nu', - 'nz' => 'whois.srs.net.nz', - 'om' => 'whois.registry.om', - 'one' => 'whois.nic.one', - 'ong' => 'whois.publicinterestregistry.net', - 'onl' => 'whois.afilias-srs.net', - 'ooo' => 'whois.nic.ooo', - 'org' => 'whois.pir.org', - 'organic' => 'whois.afilias.net', - 'ovh' => 'whois-ovh.nic.fr', - 'paris' => 'whois-paris.nic.fr', - 'partners' => 'whois.donuts.co', - 'parts' => 'whois.donuts.co', - 'pe' => 'kero.yachay.pe', - 'pf' => 'whois.registry.pf', - 'photo' => 'whois.uniregistry.net', - 'photography' => 'whois.donuts.co', - 'photos' => 'whois.donuts.co', - 'physio' => 'whois.nic.physio', - 'pics' => 'whois.uniregistry.net', - 'pictures' => 'whois.donuts.co', - 'pink' => 'whois.afilias.net', - 'pizza' => 'whois.donuts.co', - 'pl' => 'whois.dns.pl', - 'place' => 'whois.donuts.co', - 'plumbing' => 'whois.donuts.co', - 'pm' => 'whois.nic.pm', - 'pohl' => 'whois.ksregistry.net', - 'poker' => 'whois.afilias.net', - 'post' => 'whois.dotpostregistry.net', - 'pr' => 'whois.nic.pr', - 'press' => 'whois.nic.press', - 'pro' => 'whois.nic.pro', - 'prod' => 'domain-registry-whois.l.google.com', - 'productions' => 'whois.donuts.co', - 'prof' => 'domain-registry-whois.l.google.com', - 'properties' => 'whois.donuts.co', - 'property' => 'whois.uniregistry.net', - 'pt' => 'whois.dns.pt', - 'pub' => 'whois.unitedtld.com', - 'pw' => 'whois.nic.pw', - 'qa' => 'whois.registry.qa', - 'quebec' => 'whois.quebec.rs.corenic.net', - 're' => 'whois.nic.re', - 'recipes' => 'whois.donuts.co', - 'red' => 'whois.afilias.net', - 'rehab' => 'whois.rightside.co', - 'reise' => 'whois.nic.reise', - 'reisen' => 'whois.donuts.co', - 'rentals' => 'whois.donuts.co', - 'repair' => 'whois.donuts.co', - 'report' => 'whois.donuts.co', - 'republican' => 'whois.rightside.co', - 'rest' => 'whois.centralnic.com', - 'restaurant' => 'whois.donuts.co', - 'reviews' => 'whois.unitedtld.com', - 'rich' => 'whois.afilias-srs.net', - 'rio' => 'whois.gtlds.nic.br', - 'rip' => 'whois.rightside.co', - 'ro' => 'whois.rotld.ro', - 'rocks' => 'whois.unitedtld.com', - 'rodeo' => 'whois-dub.mm-registry.com', - 'rs' => 'whois.rnids.rs', - 'rsvp' => 'domain-registry-whois.l.google.com', - 'ru' => 'whois.ripn.net', - 'ruhr' => 'whois.nic.ruhr', - 'sa' => 'whois.nic.net.sa', - 'saarland' => 'whois.ksregistry.net', - 'sarl' => 'whois.donuts.co', - 'sb' => 'whois.nic.net.sb', - 'sc' => 'whois2.afilias-grs.net', - 'sca' => 'whois.nic.scb', - 'schmidt' => 'whois.nic.schmidt', - 'schule' => 'whois.donuts.co', - 'scot' => 'whois.scot.coreregistry.net', - 'se' => 'whois.iis.se', - 'services' => 'whois.donuts.co', - 'sexy' => 'whois.uniregistry.net', - 'sg' => 'whois.nic.net.sg', - 'sh' => 'whois.nic.sh', - 'shiksha' => 'whois.afilias.net', - 'shoes' => 'whois.donuts.co', - 'si' => 'whois.arnes.si', - 'singles' => 'whois.donuts.co', - 'sk' => 'whois.sk-nic.sk', - 'sm' => 'whois.nic.sm', - 'sn' => 'whois.nic.sn', - 'so' => 'whois.nic.so', - 'social' => 'whois.unitedtld.com', - 'software' => 'whois.rightside.co', - 'solar' => 'whois.donuts.co', - 'solutions' => 'whois.donuts.co', - 'soy' => 'domain-registry-whois.l.google.com', - 'space' => 'whois.nic.space', - 'spiegel' => 'whois.ksregistry.net', - 'st' => 'whois.nic.st', - 'store' => 'whois.nic.store', - 'su' => 'whois.tcinet.ru', - 'supplies' => 'whois.donuts.co', - 'supply' => 'whois.donuts.co', - 'support' => 'whois.donuts.co', - 'surf' => 'whois-dub.mm-registry.com', - 'surgery' => 'whois.donuts.co', - 'sx' => 'whois.sx', - 'sy' => 'whois.tld.sy', - 'systems' => 'whois.donuts.co', - 'tatar' => 'whois.nic.tatar', - 'tattoo' => 'whois.uniregistry.net', - 'tax' => 'whois.donuts.co', - 'tc' => 'whois.meridiantld.net', - 'technology' => 'whois.donuts.co', - 'tel' => 'whois.nic.tel', - 'tf' => 'whois.nic.tf', - 'th' => 'whois.thnic.co.th', - 'tienda' => 'whois.donuts.co', - 'tips' => 'whois.donuts.co', - 'tirol' => 'whois.nic.tirol', - 'tj' => 'whois.nic.tj', - 'tk' => 'whois.dot.tk', - 'tl' => 'whois.nic.tl', - 'tm' => 'whois.nic.tm', - 'tn' => 'whois.ati.tn', - 'to' => 'whois.tonic.to', - 'today' => 'whois.donuts.co', - 'tools' => 'whois.donuts.co', - 'top' => 'whois.nic.top', - 'town' => 'whois.donuts.co', - 'toys' => 'whois.donuts.co', - 'tp' => 'whois.nic.tl', - 'tr' => 'whois.nic.tr', - 'training' => 'whois.donuts.co', - 'travel' => 'whois.nic.travel', - 'tui' => 'whois.ksregistry.net', - 'tv' => 'tvwhois.verisign-grs.com', - 'tw' => 'whois.twnic.net.tw', - 'tz' => 'whois.tznic.or.tz', - 'ua' => 'whois.ua', - 'ug' => 'whois.co.ug', - 'uk' => 'whois.nic.uk', - 'university' => 'whois.donuts.co', - 'uol' => 'whois.gtlds.nic.br', - 'us' => 'whois.nic.us', - 'uy' => 'whois.nic.org.uy', - 'uz' => 'whois.cctld.uz', - 'vacations' => 'whois.donuts.co', - 'vc' => 'whois2.afilias-grs.net', - 've' => 'whois.nic.ve', - 'vegas' => 'whois.afilias-srs.net', - 'ventures' => 'whois.donuts.co', - 'vermögensberater' => 'whois.ksregistry.net', - 'vermögensberatung' => 'whois.ksregistry.net', - 'versicherung' => 'whois.nic.versicherung', - 'vet' => 'whois.rightside.co', - 'vg' => 'ccwhois.ksregistry.net', - 'viajes' => 'whois.donuts.co', - 'villas' => 'whois.donuts.co', - 'vision' => 'whois.donuts.co', - 'vlaanderen' => 'whois.nic.vlaanderen', - 'vodka' => 'whois-dub.mm-registry.com', - 'vote' => 'whois.afilias.net', - 'voting' => 'whois.voting.tld-box.at', - 'voto' => 'whois.afilias.net', - 'voyage' => 'whois.donuts.co', - 'vu' => 'vunic.vu', - 'wf' => 'whois.nic.wf', - 'wales' => 'whois.nic.wales', - 'wang' => 'whois.gtld.knet.cn', - 'watch' => 'whois.donuts.co', - 'website' => 'whois.nic.website', - 'wed' => 'whois.nic.wed', - 'wedding' => 'whois-dub.mm-registry.com', - 'wf' => 'whois.nic.wf', - 'wien' => 'whois.nic.wien', - 'wiki' => 'whois.nic.wiki', - 'wme' => 'whois.centralnic.com', - 'work' => 'whois-dub.mm-registry.com', - 'works' => 'whois.donuts.co', - 'world' => 'whois.donuts.co', - 'ws' => 'whois.website.ws', - 'wtc' => 'whois.nic.wtc', - 'wtf' => 'whois.donuts.co', - 'xxx' => 'whois.nic.xxx', - 'xyz' => 'whois.nic.xyz', - 'yachts' => 'whois.afilias-srs.net', - 'yoga' => 'whois-dub.mm-registry.com', - 'youtube' => 'domain-registry-whois.l.google.com', - 'yt' => 'whois.nic.yt', - 'zip' => 'domain-registry-whois.l.google.com', - 'zm' => 'whois.nic.zm', - 'zone' => 'whois.donuts.co', - 'дети' => 'whois.nic.xn--d1acj3b', - 'москва' => 'whois.nic.xn--80adxhks', - 'онлайн' => 'whois.online.rs.corenic.net', - 'орг' => 'whois.publicinterestregistry.net', - 'рус' => 'whois.nic.xn--p1acf', - 'рф' => 'whois.tcinet.ru', - 'сайт' => 'whois.site.rs.corenic.net', - 'укр' => 'whois.dotukr.com', - 'қаз' => 'whois.nic.kz', - 'الجزائر' => 'whois.nic.dz', - 'السعودية' => 'whois.nic.net.sa', - 'امارات' => 'whois.aeda.net.ae', - 'ایران' => 'whois.nic.ir', - 'بازار' => 'whois.bazaar.coreregistry.net', - 'سورية' => 'whois.tld.sy', - 'شبكة' => 'whois.nic.xn--ngbc5azd', - 'عمان' => 'whois.registry.om', - 'قطر' => 'whois.registry.qa', - 'مليسيا' => 'whois.mynic.my', - 'موقع' => 'whois.afilias-srs.net', - 'சிங்கப்பூர்' => 'whois.sgnic.sg', - 'ไทย' => 'whois.thnic.co.th', - 'みんな' => 'domain-registry-whois.l.google.com', - '中信' => 'whois.gtld.knet.cn', - '中国' => 'cwhois.cnnic.cn', - '中國' => 'cwhois.cnnic.cn', - '中文网' => 'whois.afilias-srs.net', - '企业' => 'whois.donuts.co', - '佛山' => 'whois.ngtld.cn', - '公司' => 'whois.ngtld.cn', - '公益' => 'whois.conac.cn', - '台湾' => 'whois.twnic.net.tw', - '台灣' => 'whois.twnic.net.tw', - '商城' => 'whois.gtld.knet.cn', - '在线' => 'whois.afilias-srs.net', - '广东' => 'whois.ngtld.cn', - '我爱你' => 'whois.gtld.knet.cn', - '手机' => 'whois.afilias-srs.net', - '政务' => 'whois.conac.cn', - '新加坡' => 'whois.sgnic.sg', - '新加坡' => 'whois.sgnic.sg', - '游戏' => 'whois.donuts.co', - '移动' => 'whois.afilias.net', - '组织机构' => 'whois.publicinterestregistry.net', - '网络' => 'whois.ngtld.cn', - '集团' => 'whois.gtld.knet.cn', - '香港' => 'whois.hkirc.hk', - ]; - - public $ip = [ - 'whois.lacnic.net', - 'whois.apnic.net', - 'whois.arin.net', - 'whois.ripe.net', - ]; -} diff --git a/public/whois/whois-php/src/Whois/WhoisException.php b/public/whois/whois-php/src/Whois/WhoisException.php deleted file mode 100644 index 57bba77..0000000 --- a/public/whois/whois-php/src/Whois/WhoisException.php +++ /dev/null @@ -1,8 +0,0 @@ -server; + } + + public function query(string $target, int $timeout = 5): WhoisResponse { + $sock = @fsockopen($this->server, self::PORT, $errno, $errstr, $timeout); + if(!$sock) throw new \RuntimeException('WhoisClient: ' . $errstr); + + try { + fwrite($sock, $target . "\r\n"); + + $lines = []; + while($line = fgets($sock)) + $lines[] = trim($line); + } finally { + fclose($sock); + } + + return new WhoisResponse($this->server, $lines); + } + + public function lookup(string $target, int $timeout = 5): WhoisResult { + $target = idn_to_ascii(mb_strtolower($target), IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46); + $client = $this; + $response = null; + $responses = []; + + try { + for(;;) { + $response = $client->query($target); + $responses[] = $response; + + $server = $response->findNextWhoisServer(); + if($server === '' || $server === $this->server) + break; + + $client = new WhoisClient($server); + } + } catch(\RuntimeException $ex) { + if(empty($responses)) + throw $ex; + } + + return new WhoisResult($target, array_reverse($responses)); + } +} diff --git a/src/Whois/WhoisResponse.php b/src/Whois/WhoisResponse.php new file mode 100644 index 0000000..b1cd07b --- /dev/null +++ b/src/Whois/WhoisResponse.php @@ -0,0 +1,60 @@ +server; + } + + public function getLines(): array { + return $this->lines; + } + + public function getText(): string { + return implode(PHP_EOL, $this->lines); + } + + public function findNextWhoisServer(): string { + $server = ''; + + foreach($this->lines as $line) { + $parts = explode(':', strtolower($line), 2); + if(in_array(trim($parts[0]), self::WHOIS_SERVER_PREFIXES)) { + $server = trim($parts[1]); + if(str_contains($server, '://')) { + $server = ''; + continue; + } + break; + } + } + + return $this->server === $server ? '' : $server; + } + + public function jsonSerialize(): mixed { + return [ + 'server' => $this->server, + 'lines' => $this->lines, + ]; + } + + public function __serialize(): array { + return [ + 'server' => $this->server, + 'lines' => $this->lines, + ]; + } + + public function __unserialize(array $stored): void { + $this->server = $stored['server']; + $this->lines = $stored['lines']; + } +} diff --git a/src/Whois/WhoisResult.php b/src/Whois/WhoisResult.php new file mode 100644 index 0000000..255a69a --- /dev/null +++ b/src/Whois/WhoisResult.php @@ -0,0 +1,44 @@ +target; + } + + public function getResponses(): array { + return $this->responses; + } + + public function getResponse(int $index): WhoisResponse { + return $this->responses[$index]; + } + + public function getResponseCount(): int { + return count($this->responses); + } + + public function jsonSerialize(): mixed { + return [ + 'target' => $this->target, + 'responses' => $this->responses, + ]; + } + + public function __serialize(): array { + return [ + 'target' => $this->target, + 'responses' => $this->responses, + ]; + } + + public function __unserialize(array $stored): void { + $this->target = $stored['target']; + $this->responses = $stored['responses']; + } +} diff --git a/tpl/ascii.php b/tpl/ascii.php index c8c83d0..86522d2 100644 --- a/tpl/ascii.php +++ b/tpl/ascii.php @@ -1,5 +1,5 @@ extends('home/master'); +$self->extends('master'); $self->header_title = 'flash.moe / ascii table'; $self->header_minimal = true; diff --git a/tpl/contact.php b/tpl/contact.php index 90d6e3a..149b94b 100644 --- a/tpl/contact.php +++ b/tpl/contact.php @@ -1,5 +1,5 @@ extends('home/master'); +$self->extends('master'); $self->header_title = 'flash.moe / contact'; diff --git a/tpl/master.php b/tpl/master.php index adc86f4..4b91f1a 100644 --- a/tpl/master.php +++ b/tpl/master.php @@ -43,7 +43,7 @@ getBlock('container');?> footer_onload) && is_array($self->footer_onload)): ?> +