Much better IDN support, fixes #73

This commit is contained in:
Pinga 2024-01-23 12:58:01 +02:00
parent 4d57ad71a1
commit 137f8170e2
16 changed files with 235 additions and 60 deletions

View file

@ -23,7 +23,7 @@ class ApplicationsController extends Controller
return $response->withHeader('Location', '/domains')->withStatus(302);
}
}
public function createApplication(Request $request, Response $response)
{
if ($request->getMethod() === 'POST') {
@ -31,6 +31,16 @@ class ApplicationsController extends Controller
$data = $request->getParsedBody();
$db = $this->container->get('db');
$domainName = $data['domainName'] ?? null;
// Convert to Punycode if the domain is not in ASCII
if (!mb_detect_encoding($domainName, 'ASCII', true)) {
$convertedDomain = idn_to_ascii($domainName, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if ($convertedDomain === false) {
$this->container->get('flash')->addMessage('error', 'Application name conversion to Punycode failed');
return $response->withHeader('Location', '/application/create')->withStatus(302);
} else {
$domainName = $convertedDomain;
}
}
$registrar_id = $data['registrar'] ?? null;
$registrars = $db->select("SELECT id, clid, name FROM registrar");
if ($_SESSION["auth_roles"] != 0) {

View file

@ -27,6 +27,17 @@ class DomainsController extends Controller
$claims = $data['claims'] ?? null;
if ($domainName) {
// Convert to Punycode if the domain is not in ASCII
if (!mb_detect_encoding($domainName, 'ASCII', true)) {
$convertedDomain = idn_to_ascii($domainName, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if ($convertedDomain === false) {
$this->container->get('flash')->addMessage('error', 'Domain conversion to Punycode failed');
return $response->withHeader('Location', '/domain/check')->withStatus(302);
} else {
$domainName = $convertedDomain;
}
}
$domainName = preg_replace('/[^\p{L}0-9-.]/u', '', $domainName);
$parts = extractDomainAndTLD($domainName);
@ -105,6 +116,16 @@ class DomainsController extends Controller
$data = $request->getParsedBody();
$db = $this->container->get('db');
$domainName = $data['domainName'] ?? null;
// Convert to Punycode if the domain is not in ASCII
if (!mb_detect_encoding($domainName, 'ASCII', true)) {
$convertedDomain = idn_to_ascii($domainName, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if ($convertedDomain === false) {
$this->container->get('flash')->addMessage('error', 'Domain conversion to Punycode failed');
return $response->withHeader('Location', '/domain/create')->withStatus(302);
} else {
$domainName = $convertedDomain;
}
}
$registrar_id = $data['registrar'] ?? null;
$registrars = $db->select("SELECT id, clid, name FROM registrar");
if ($_SESSION["auth_roles"] != 0) {
@ -2229,6 +2250,16 @@ class DomainsController extends Controller
$data = $request->getParsedBody();
$db = $this->container->get('db');
$domainName = $data['domainName'] ?? null;
// Convert to Punycode if the domain is not in ASCII
if (!mb_detect_encoding($domainName, 'ASCII', true)) {
$convertedDomain = idn_to_ascii($domainName, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if ($convertedDomain === false) {
$this->container->get('flash')->addMessage('error', 'Domain conversion to Punycode failed');
return $response->withHeader('Location', '/transfers')->withStatus(302);
} else {
$domainName = $convertedDomain;
}
}
$registrar_id = $data['registrar'] ?? null;
$authInfo = $data['authInfo'] ?? null;
$transferYears = $data['transferYears'] ?? null;

View file

@ -34,6 +34,17 @@ class HostsController extends Controller
if ($hostName) {
$hostModel = new Host($this->container->get('db'));
// Convert to Punycode if the host is not in ASCII
if (!mb_detect_encoding($hostName, 'ASCII', true)) {
$convertedDomain = idn_to_ascii($hostName, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if ($convertedDomain === false) {
$this->container->get('flash')->addMessage('error', 'Host conversion to Punycode failed');
return $response->withHeader('Location', '/host/create')->withStatus(302);
} else {
$hostName = $convertedDomain;
}
}
if (preg_match('/^([A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9]){0,1}\.){1,125}[A-Z0-9]([A-Z0-9-]{0,61}[A-Z0-9])$/i', $hostName) && strlen($hostName) < 254) {
$host_id_already_exist = $hostModel->getHostByNom($hostName);
if ($host_id_already_exist) {
@ -235,14 +246,14 @@ class HostsController extends Controller
function isValidHostname($hostname) {
$hostname = trim($hostname);
// Check for IDN and convert to ASCII if necessary
if (mb_detect_encoding($hostname, 'ASCII', true) === false) {
$hostname = idn_to_ascii($hostname, 0, INTL_IDNA_VARIANT_UTS46);
$hostname = idn_to_ascii($hostname, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
}
// Regular expression for validating a hostname (simplified version)
$pattern = '/^([a-zA-Z0-9-]{1,63}\.){1,}[a-zA-Z]{2,63}$/';
// Regular expression for validating a hostname
$pattern = '/^((xn--[a-zA-Z0-9-]{1,63}|[a-zA-Z0-9-]{1,63})\.){2,}(xn--[a-zA-Z0-9-]{2,63}|[a-zA-Z]{2,63})$/';
return preg_match($pattern, $hostname);
}
@ -306,14 +317,14 @@ class HostsController extends Controller
function isValidHostname($hostname) {
$hostname = trim($hostname);
// Check for IDN and convert to ASCII if necessary
if (mb_detect_encoding($hostname, 'ASCII', true) === false) {
$hostname = idn_to_ascii($hostname, 0, INTL_IDNA_VARIANT_UTS46);
$hostname = idn_to_ascii($hostname, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
}
// Regular expression for validating a hostname (simplified version)
$pattern = '/^([a-zA-Z0-9-]{1,63}\.){1,}[a-zA-Z]{2,63}$/';
// Regular expression for validating a hostname
$pattern = '/^((xn--[a-zA-Z0-9-]{1,63}|[a-zA-Z0-9-]{1,63})\.){2,}(xn--[a-zA-Z0-9-]{2,63}|[a-zA-Z]{2,63})$/';
return preg_match($pattern, $hostname);
}

View file

@ -345,7 +345,7 @@ class SystemController extends Controller
return $response->withHeader('Location', '/registry/tld/create')->withStatus(302);
}
switch ($data['extension']) {
switch ($data['script']) {
case 'ascii':
$idntable = '/^(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-)(.(?!-)(?!.*--)[A-Z0-9-]{1,63}(?<!-))*$/i';
break;
@ -365,10 +365,22 @@ class SystemController extends Controller
try {
$db->beginTransaction();
$currentDateTime = new \DateTime();
$crdate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp
// Convert to Punycode if the domain is not in ASCII
if (!mb_detect_encoding($data['extension'], 'ASCII', true)) {
$data['extension'] = str_replace('.', '', $data['extension']);
$convertedDomain = idn_to_ascii($data['extension'], IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if ($convertedDomain === false) {
$this->container->get('flash')->addMessage('error', 'TLD conversion to Punycode failed');
return $response->withHeader('Location', '/registry/tld/create')->withStatus(302);
} else {
$data['extension'] = '.' . $convertedDomain;
}
}
$db->insert('domain_tld', [
'tld' => $data['extension'],
'idn_table' => $idntable,
@ -536,11 +548,11 @@ class SystemController extends Controller
if ($args) {
$args = trim($args);
if (!preg_match('/^\.[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)?[^\.]$/', $args)) {
if (!preg_match('/^\.(xn--[a-zA-Z0-9-]+|[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)?)$/', $args)) {
$this->container->get('flash')->addMessage('error', 'Invalid TLD format');
return $response->withHeader('Location', '/registry/tlds')->withStatus(302);
}
$validators = [
'extension' => v::stringType()->notEmpty()->length(3, 64),
'createm0' => v::numericVal()->between(0.00, 9999999.99, true),
@ -827,7 +839,7 @@ class SystemController extends Controller
if ($args) {
$args = trim($args);
if (!preg_match('/^\.[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)?[^\.]$/', $args)) {
if (!preg_match('/^\.(xn--[a-zA-Z0-9-]+|[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)?)$/', $args)) {
$this->container->get('flash')->addMessage('error', 'Invalid TLD format');
return $response->withHeader('Location', '/registry/tlds')->withStatus(302);
}