Skip to content

Instantly share code, notes, and snippets.

@oneluiz
Last active December 21, 2024 17:29
Show Gist options
  • Save oneluiz/280854f5120320c76aef5bcd2cf7d6f1 to your computer and use it in GitHub Desktop.
Save oneluiz/280854f5120320c76aef5bcd2cf7d6f1 to your computer and use it in GitHub Desktop.
PHP code to get WHOIS information of a domain
<?php
/**
* Servicio para realizar consultas WHOIS de dominios.
*
* Esta clase implementa el patrón Singleton para garantizar que solo exista
* una instancia del servicio, evitando consultas innecesarias y reduciendo el
* consumo de recursos.
*
* @author Luis Cortés
*/
class WhoisService {
private static ?WhoisService $instance = null;
private array $whoisServers;
/**
* Constructor privado para inicializar servidores WHOIS.
* Se utiliza para cargar una lista de servidores para diferentes extensiones de dominio.
*/
private function __construct() {
$this->whoisServers = [
'.com' => ['whois.crsnic.net', 'No match for'],
'.net' => ['whois.crsnic.net', 'No match for'],
'.bo' => ['whois.nic.bo', 'solo acepta consultas con dominios .bo'],
'.mx' => ['whois.nic.mx', 'No_Se_Encontro_El_Objeto'],
'.pe' => ['whois.nic.pe', 'No Object Found'],
'.co' => ['whois.nic.co', 'Not found'],
'.es' => ['whois.nic.es', 'Not found'],
'.uk' => ['whois.nic.uk', 'No match for'],
'.org' => ['whois.pir.org', 'NOT FOUND'],
'.info'=> ['whois.afilias.net', 'NOT FOUND'],
'.io' => ['whois.nic.io', 'NOT FOUND'],
'.ai' => ['whois.ai', 'No Object Found'],
'.us' => ['whois.nic.us', 'Not found'],
'.ca' => ['whois.cira.ca', 'Domain status: available'],
'.fr' => ['whois.nic.fr', 'No entries found'],
'.it' => ['whois.nic.it', 'AVAILABLE'],
'.au' => ['whois.auda.org.au', 'No Data Found']
];
}
/**
* Devuelve la instancia única del servicio WHOIS (Singleton).
*
* Se utiliza el patrón Singleton para evitar instancias duplicadas,
* asegurando que haya una única fuente de verdad para las consultas WHOIS.
*
* @return WhoisService
*/
public static function getInstance(): WhoisService {
return self::$instance ??= new WhoisService();
}
/**
* Realiza una consulta WHOIS a un servidor especificado.
*
* @param string $domain Nombre de dominio sin extensión.
* @param string $extension Extensión de dominio (e.g. .com, .net).
* @return string Mensaje HTML con el resultado de la consulta.
* @throws InvalidArgumentException Si la extensión del dominio no está soportada.
*/
public function performWhoisQuery(string $domain, string $extension): string {
$serverInfo = $this->whoisServers[$extension] ?? null;
if (!$serverInfo) {
throw new InvalidArgumentException("Unsupported domain extension: $extension");
}
[$whoisServer, $notFoundMsg] = $serverInfo;
$response = $this->queryWhoisServer($whoisServer, $domain . $extension);
return $this->generateResponse($domain . $extension, $response, $notFoundMsg);
}
/**
* Realiza la consulta al servidor WHOIS.
*
* Este método establece una conexión socket al servidor WHOIS especificado
* y realiza la consulta de disponibilidad del dominio. Devuelve el resultado
* completo de la consulta.
*
* @param string $whoisServer Servidor WHOIS a consultar.
* @param string $domain Nombre de dominio completo (con extensión).
* @return array Estado de la consulta y datos recibidos.
*/
private function queryWhoisServer(string $whoisServer, string $domain): array {
$response = ['status' => false, 'data' => ''];
try {
$sock = @fsockopen($whoisServer, 43, $errno, $errstr, 10);
if ($sock) {
fwrite($sock, $domain . "\r\n");
while (!feof($sock)) {
$response['data'] .= fgets($sock, 128);
}
fclose($sock);
$response['status'] = true;
}
} catch (Throwable $e) {
error_log("WHOIS error: " . $e->getMessage());
}
return $response;
}
/**
* Genera el mensaje de respuesta basado en el resultado de la consulta.
*
* Determina si el dominio está disponible comparando el resultado de la
* consulta con el mensaje que indica que no se encontró el dominio.
*
* @param string $domain Nombre de dominio consultado.
* @param array $result Resultado de la consulta (estado y datos).
* @param string $notFoundMsg Mensaje que indica que el dominio está disponible.
* @return string HTML con la respuesta de dominio disponible o no.
*/
private function generateResponse(string $domain, array $result, string $notFoundMsg): string {
$available = $result['status'] && str_contains($result['data'], $notFoundMsg);
$whoisData = htmlspecialchars($result['data'] ?? '');
return $available
? $this->successTemplate($domain)
: $this->errorTemplate($domain, $whoisData);
}
/**
* Plantilla de mensaje para dominios disponibles.
*
* @param string $domain
* @return string HTML con mensaje de dominio disponible.
*/
private function successTemplate(string $domain): string {
return '<div class="alert alert-success alert-dismissible" role="alert">'
. '<button type="button" class="close" data-dismiss="alert">&times;</button>'
. '<span>Yes! Your domain <strong>' . htmlspecialchars($domain) . '</strong> is available. Buy it now!</span>'
. '<button class="btn btn-success ml-3" type="button">Buy this domain</button></div>';
}
/**
* Plantilla de mensaje para dominios no disponibles.
*
* @param string $domain
* @param string $whoisData
* @return string HTML con mensaje de dominio no disponible.
*/
private function errorTemplate(string $domain, string $whoisData): string {
return '<div class="alert alert-light alert-dismissible" role="alert">'
. '<button type="button" class="close" data-dismiss="alert">&times;</button>'
. '<span>Sorry, <strong>' . htmlspecialchars($domain) . '</strong> is taken.</span>'
. '<a class="btn btn-danger ml-3" data-toggle="collapse" href="#collapseDetails">View details</a>'
. '<div class="collapse" id="collapseDetails"><pre>' . $whoisData . '</pre></div></div>';
}
}
// Uso del servicio para manejar la entrada de usuario y ejecutar consultas WHOIS.
try {
$domainName = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING) ?? '';
$domainExt = filter_input(INPUT_POST, 'Ext', FILTER_SANITIZE_STRING) ?? '';
if ($domainName && $domainExt) {
$cleanDomain = preg_replace('/^(www\\.|http:\/\/|\/)/', '', $domainName);
echo WhoisService::getInstance()->performWhoisQuery($cleanDomain, $domainExt);
}
} catch (Exception $e) {
echo '<div class="alert alert-danger">Error: ' . htmlspecialchars($e->getMessage()) . '</div>';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment