mirror of
https://github.com/getnamingo/registry.git
synced 2025-07-27 12:56:12 +02:00
Big RDAP update
This commit is contained in:
parent
8ff392d8a0
commit
8d63b93d1f
2 changed files with 161 additions and 44 deletions
|
@ -5,6 +5,7 @@ CREATE DATABASE IF NOT EXISTS `registry`;
|
||||||
CREATE TABLE IF NOT EXISTS `registry`.`domain_tld` (
|
CREATE TABLE IF NOT EXISTS `registry`.`domain_tld` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
`tld` varchar(32) NOT NULL,
|
`tld` varchar(32) NOT NULL,
|
||||||
|
`idn_table` varchar(255) NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `tld` (`tld`)
|
UNIQUE KEY `tld` (`tld`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='domain tld';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='domain tld';
|
||||||
|
@ -542,11 +543,11 @@ CREATE TABLE `premium_domain_pricing` (
|
||||||
FOREIGN KEY (`tld_id`) REFERENCES `domain_tld`(`id`)
|
FOREIGN KEY (`tld_id`) REFERENCES `domain_tld`(`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Premium Domains';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Premium Domains';
|
||||||
|
|
||||||
INSERT INTO `registry`.`domain_tld` VALUES('1','.COM.XX');
|
INSERT INTO `registry`.`domain_tld` VALUES('1','.COM.XX','/^(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-)(\.(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-))*$/i');
|
||||||
INSERT INTO `registry`.`domain_tld` VALUES('2','.ORG.XX');
|
INSERT INTO `registry`.`domain_tld` VALUES('2','.ORG.XX','/^(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-)(\.(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-))*$/i');
|
||||||
INSERT INTO `registry`.`domain_tld` VALUES('3','.INFO.XX');
|
INSERT INTO `registry`.`domain_tld` VALUES('3','.INFO.XX','/^(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-)(\.(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-))*$/i');
|
||||||
INSERT INTO `registry`.`domain_tld` VALUES('4','.PRO.XX');
|
INSERT INTO `registry`.`domain_tld` VALUES('4','.PRO.XX','/^(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-)(\.(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-))*$/i');
|
||||||
INSERT INTO `registry`.`domain_tld` VALUES('5','.XX');
|
INSERT INTO `registry`.`domain_tld` VALUES('5','.XX','/^(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-)(\.(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-))*$/i');
|
||||||
|
|
||||||
INSERT INTO `registry`.`domain_price` VALUES('1','1','create','0.00','5.00','10.00','15.00','20.00','25.00','30.00','35.00','40.00','45.00','50.00');
|
INSERT INTO `registry`.`domain_price` VALUES('1','1','create','0.00','5.00','10.00','15.00','20.00','25.00','30.00','35.00','40.00','45.00','50.00');
|
||||||
INSERT INTO `registry`.`domain_price` VALUES('2','1','renew','0.00','5.00','10.00','15.00','20.00','25.00','30.00','35.00','40.00','45.00','50.00');
|
INSERT INTO `registry`.`domain_price` VALUES('2','1','renew','0.00','5.00','10.00','15.00','20.00','25.00','30.00','35.00','40.00','45.00','50.00');
|
||||||
|
|
192
rdap/rdap.php
192
rdap/rdap.php
|
@ -4,8 +4,35 @@ if (!extension_loaded('swoole')) {
|
||||||
die('Swoole extension must be installed');
|
die('Swoole extension must be installed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapContactToVCard($contactDetails, $role) {
|
||||||
|
return [
|
||||||
|
'objectClassName' => 'entity',
|
||||||
|
'roles' => [$role],
|
||||||
|
'vcardArray' => [
|
||||||
|
"vcard",
|
||||||
|
[
|
||||||
|
["version", "4.0"],
|
||||||
|
["fn", $contactDetails['name']],
|
||||||
|
["org", $contactDetails['org']],
|
||||||
|
["adr", [
|
||||||
|
"", // Post office box
|
||||||
|
$contactDetails['street1'], // Extended address
|
||||||
|
$contactDetails['street2'], // Street address
|
||||||
|
$contactDetails['city'], // Locality
|
||||||
|
$contactDetails['sp'], // Region
|
||||||
|
$contactDetails['pc'], // Postal code
|
||||||
|
$contactDetails['cc'] // Country name
|
||||||
|
]],
|
||||||
|
["tel", $contactDetails['voice'], ["type" => "voice"]],
|
||||||
|
["tel", $contactDetails['fax'], ["type" => "fax"]],
|
||||||
|
["email", $contactDetails['email']],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
// Create a Swoole HTTP server
|
// Create a Swoole HTTP server
|
||||||
$http = new Swoole\Http\Server('0.0.0.0', 8080);
|
$http = new Swoole\Http\Server('0.0.0.0', 7500);
|
||||||
|
|
||||||
// Register a callback to handle incoming requests
|
// Register a callback to handle incoming requests
|
||||||
$http->on('request', function ($request, $response) {
|
$http->on('request', function ($request, $response) {
|
||||||
|
@ -59,8 +86,69 @@ $http->start();
|
||||||
|
|
||||||
function handleDomainQuery($request, $response, $pdo, $domainName) {
|
function handleDomainQuery($request, $response, $pdo, $domainName) {
|
||||||
// Extract and validate the domain name from the request
|
// Extract and validate the domain name from the request
|
||||||
$domain = $domainName;
|
$domain = trim($domainName);
|
||||||
// ... Perform validation as in the WHOIS server ...
|
|
||||||
|
// Empty domain check
|
||||||
|
if (!$domain) {
|
||||||
|
$response->header('Content-Type', 'application/json');
|
||||||
|
$response->status(400); // Bad Request
|
||||||
|
$response->end(json_encode(['error' => 'Please enter a domain name']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check domain length
|
||||||
|
if (strlen($domain) > 68) {
|
||||||
|
$response->header('Content-Type', 'application/json');
|
||||||
|
$response->status(400); // Bad Request
|
||||||
|
$response->end(json_encode(['error' => 'Domain name is too long']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for prohibited patterns in domain names
|
||||||
|
if (preg_match("/(^-|^\.|-\.|\.-|--|\.\.|-$|\.$)/", $domain)) {
|
||||||
|
$response->header('Content-Type', 'application/json');
|
||||||
|
$response->status(400); // Bad Request
|
||||||
|
$response->end(json_encode(['error' => 'Domain name invalid format']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract TLD from the domain
|
||||||
|
$parts = explode('.', $domain);
|
||||||
|
$tld = "." . end($parts);
|
||||||
|
|
||||||
|
// Check if the TLD exists in the domain_tld table
|
||||||
|
$stmtTLD = $pdo->prepare("SELECT COUNT(*) FROM domain_tld WHERE tld = :tld");
|
||||||
|
$stmtTLD->bindParam(':tld', $tld, PDO::PARAM_STR);
|
||||||
|
$stmtTLD->execute();
|
||||||
|
$tldExists = $stmtTLD->fetchColumn();
|
||||||
|
|
||||||
|
if (!$tldExists) {
|
||||||
|
$response->header('Content-Type', 'application/json');
|
||||||
|
$response->status(400); // Bad Request
|
||||||
|
$response->end(json_encode(['error' => 'Invalid TLD. Please search only allowed TLDs']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the IDN regex for the given TLD
|
||||||
|
$stmtRegex = $pdo->prepare("SELECT idn_table FROM domain_tld WHERE tld = :tld");
|
||||||
|
$stmtRegex->bindParam(':tld', $tld, PDO::PARAM_STR);
|
||||||
|
$stmtRegex->execute();
|
||||||
|
$idnRegex = $stmtRegex->fetchColumn();
|
||||||
|
|
||||||
|
if (!$idnRegex) {
|
||||||
|
$response->header('Content-Type', 'application/json');
|
||||||
|
$response->status(400); // Bad Request
|
||||||
|
$response->end(json_encode(['error' => 'Failed to fetch domain IDN table']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for invalid characters using fetched regex
|
||||||
|
if (!preg_match($idnRegex, $domain)) {
|
||||||
|
$response->header('Content-Type', 'application/json');
|
||||||
|
$response->status(400); // Bad Request
|
||||||
|
$response->end(json_encode(['error' => 'Domain name invalid format']));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the RDAP lookup
|
// Perform the RDAP lookup
|
||||||
try {
|
try {
|
||||||
|
@ -73,6 +161,7 @@ function handleDomainQuery($request, $response, $pdo, $domainName) {
|
||||||
// Check if the domain exists
|
// Check if the domain exists
|
||||||
if (!$domainDetails) {
|
if (!$domainDetails) {
|
||||||
// Domain not found, respond with a 404 error
|
// Domain not found, respond with a 404 error
|
||||||
|
$response->header('Content-Type', 'application/json');
|
||||||
$response->status(404);
|
$response->status(404);
|
||||||
$response->end(json_encode([
|
$response->end(json_encode([
|
||||||
'errorCode' => 404,
|
'errorCode' => 404,
|
||||||
|
@ -102,8 +191,35 @@ function handleDomainQuery($request, $response, $pdo, $domainName) {
|
||||||
$stmt4->execute();
|
$stmt4->execute();
|
||||||
$registrantDetails = $stmt4->fetch(PDO::FETCH_ASSOC);
|
$registrantDetails = $stmt4->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Query 5: Get admin and tech contacts (similar to registrant, with different conditions)
|
// Query 5: Get admin, billing and tech contacts
|
||||||
// ...
|
$stmtMap = $pdo->prepare("SELECT contact_id, type FROM domain_contact_map WHERE domain_id = :domain_id");
|
||||||
|
$stmtMap->bindParam(':domain_id', $domainDetails['id'], PDO::PARAM_INT);
|
||||||
|
$stmtMap->execute();
|
||||||
|
$contactMap = $stmtMap->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
$adminDetails = [];
|
||||||
|
$techDetails = [];
|
||||||
|
$billingDetails = [];
|
||||||
|
|
||||||
|
foreach ($contactMap as $map) {
|
||||||
|
$stmtDetails = $pdo->prepare("SELECT contact.identifier, contact_postalInfo.name, contact_postalInfo.org, contact_postalInfo.street1, contact_postalInfo.street2, contact_postalInfo.street3, contact_postalInfo.city, contact_postalInfo.sp, contact_postalInfo.pc, contact_postalInfo.cc, contact.voice, contact.voice_x, contact.fax, contact.fax_x, contact.email FROM contact, contact_postalInfo WHERE contact.id = :contact_id AND contact_postalInfo.contact_id = contact.id");
|
||||||
|
$stmtDetails->bindParam(':contact_id', $map['contact_id'], PDO::PARAM_INT);
|
||||||
|
$stmtDetails->execute();
|
||||||
|
|
||||||
|
$contactDetails = $stmtDetails->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
switch ($map['type']) {
|
||||||
|
case 'admin':
|
||||||
|
$adminDetails[] = $contactDetails;
|
||||||
|
break;
|
||||||
|
case 'tech':
|
||||||
|
$techDetails[] = $contactDetails;
|
||||||
|
break;
|
||||||
|
case 'billing':
|
||||||
|
$billingDetails[] = $contactDetails;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Query 6: Get nameservers
|
// Query 6: Get nameservers
|
||||||
$stmt6 = $pdo->prepare("
|
$stmt6 = $pdo->prepare("
|
||||||
|
@ -116,6 +232,23 @@ function handleDomainQuery($request, $response, $pdo, $domainName) {
|
||||||
$stmt6->execute();
|
$stmt6->execute();
|
||||||
$nameservers = $stmt6->fetchAll(PDO::FETCH_ASSOC);
|
$nameservers = $stmt6->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// Define the basic events
|
||||||
|
$events = [
|
||||||
|
['eventAction' => 'registration', 'eventDate' => $domainDetails['crdate']],
|
||||||
|
['eventAction' => 'expiration', 'eventDate' => $domainDetails['exdate']],
|
||||||
|
['eventAction' => 'last rdap database update', 'eventDate' => date('Y-m-d\TH:i:s\Z')],
|
||||||
|
];
|
||||||
|
|
||||||
|
// Check if domain last update is set and not empty
|
||||||
|
if (isset($domainDetails['update']) && !empty($domainDetails['update'])) {
|
||||||
|
$events[] = ['eventAction' => 'last domain update', 'eventDate' => date('Y-m-d', strtotime($domainDetails['update']))];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if domain transfer date is set and not empty
|
||||||
|
if (isset($domainDetails['trdate']) && !empty($domainDetails['trdate'])) {
|
||||||
|
$events[] = ['eventAction' => 'domain transfer', 'eventDate' => date('Y-m-d', strtotime($domainDetails['trdate']))];
|
||||||
|
}
|
||||||
|
|
||||||
// Construct the RDAP response in JSON format
|
// Construct the RDAP response in JSON format
|
||||||
$rdapResponse = [
|
$rdapResponse = [
|
||||||
'rdapConformance' => [
|
'rdapConformance' => [
|
||||||
|
@ -124,39 +257,21 @@ function handleDomainQuery($request, $response, $pdo, $domainName) {
|
||||||
'icann_rdap_technical_implementation_guide_0',
|
'icann_rdap_technical_implementation_guide_0',
|
||||||
],
|
],
|
||||||
'objectClassName' => 'domain',
|
'objectClassName' => 'domain',
|
||||||
'entities' => [
|
'entities' => array_merge(
|
||||||
[
|
[
|
||||||
'objectClassName' => 'entity',
|
mapContactToVCard($registrantDetails, 'registrant')
|
||||||
'roles' => ['registrant'],
|
|
||||||
'vcardArray' => [
|
|
||||||
"vcard",
|
|
||||||
[
|
|
||||||
["version", "4.0"],
|
|
||||||
["fn", $registrantDetails['name']],
|
|
||||||
["org", $registrantDetails['org']],
|
|
||||||
["adr", [
|
|
||||||
"", // Post office box
|
|
||||||
$registrantDetails['street1'], // Extended address
|
|
||||||
$registrantDetails['street2'], // Street address
|
|
||||||
$registrantDetails['city'], // Locality
|
|
||||||
$registrantDetails['sp'], // Region
|
|
||||||
$registrantDetails['pc'], // Postal code
|
|
||||||
$registrantDetails['cc'] // Country name
|
|
||||||
]],
|
|
||||||
["tel", $registrantDetails['voice'], ["type" => "voice"]],
|
|
||||||
["tel", $registrantDetails['fax'], ["type" => "fax"]],
|
|
||||||
["email", $registrantDetails['email']],
|
|
||||||
// ... Additional vCard properties ...
|
|
||||||
]
|
|
||||||
],
|
|
||||||
],
|
|
||||||
// ... Additional entities for admin, tech ...
|
|
||||||
],
|
|
||||||
'events' => [
|
|
||||||
['eventAction' => 'registration', 'eventDate' => $domainDetails['crdate']],
|
|
||||||
['eventAction' => 'expiration', 'eventDate' => $domainDetails['exdate']],
|
|
||||||
// ... Additional events ...
|
|
||||||
],
|
],
|
||||||
|
array_map(function ($contact) {
|
||||||
|
return mapContactToVCard($contact, 'admin');
|
||||||
|
}, $adminDetails),
|
||||||
|
array_map(function ($contact) {
|
||||||
|
return mapContactToVCard($contact, 'tech');
|
||||||
|
}, $techDetails),
|
||||||
|
array_map(function ($contact) {
|
||||||
|
return mapContactToVCard($contact, 'billing');
|
||||||
|
}, $billingDetails)
|
||||||
|
),
|
||||||
|
'events' => $events,
|
||||||
'handle' => $domainDetails['id'] . '',
|
'handle' => $domainDetails['id'] . '',
|
||||||
'ldhName' => $domain,
|
'ldhName' => $domain,
|
||||||
'status' => $statuses,
|
'status' => $statuses,
|
||||||
|
@ -175,8 +290,8 @@ function handleDomainQuery($request, $response, $pdo, $domainName) {
|
||||||
'nameservers' => array_map(function ($nameserverDetails) {
|
'nameservers' => array_map(function ($nameserverDetails) {
|
||||||
return [
|
return [
|
||||||
'objectClassName' => 'nameserver',
|
'objectClassName' => 'nameserver',
|
||||||
'handle' => $nameserverDetails['host_id'] . '', // Use the 'host_id' from the query
|
'handle' => $nameserverDetails['host_id'] . '',
|
||||||
'ldhName' => $nameserverDetails['name'], // Use the 'name' from the query
|
'ldhName' => $nameserverDetails['name'],
|
||||||
'links' => [
|
'links' => [
|
||||||
[
|
[
|
||||||
'href' => 'http://example.com/rdap/nameserver/' . $nameserverDetails['name'],
|
'href' => 'http://example.com/rdap/nameserver/' . $nameserverDetails['name'],
|
||||||
|
@ -193,6 +308,7 @@ function handleDomainQuery($request, $response, $pdo, $domainName) {
|
||||||
$response->header('Content-Type', 'application/json');
|
$response->header('Content-Type', 'application/json');
|
||||||
$response->end(json_encode($rdapResponse, JSON_UNESCAPED_SLASHES));
|
$response->end(json_encode($rdapResponse, JSON_UNESCAPED_SLASHES));
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
|
$response->header('Content-Type', 'application/json');
|
||||||
$response->end(json_encode(['error' => 'Error connecting to the RDAP database']));
|
$response->end(json_encode(['error' => 'Error connecting to the RDAP database']));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue