Browse Source

Add reg/edit.php and regParseRecord()

Miraty 1 year ago
parent
commit
2570d09ba9

+ 5 - 5
fn/dns.php

@@ -70,11 +70,11 @@ function knotcZoneExec(string $zone, array $cmd, string $action = NULL): void {
 }
 }
 
 
 function checkIpFormat(string $ip): string {
 function checkIpFormat(string $ip): string {
-	if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
-		return 'A';
-	if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
-		return 'AAAA';
-	output(403, _('IP address malformed.'));
+	return match ($ip) {
+		filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) => 'AAAA',
+		filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) => 'A',
+		default => output(403, _('IP address malformed.')),
+	};
 }
 }
 
 
 function checkAbsoluteDomainFormat(string $domain): void { // If the domain must end with a dot
 function checkAbsoluteDomainFormat(string $domain): void { // If the domain must end with a dot

+ 11 - 11
fn/ns.php

@@ -1,6 +1,6 @@
 <?php declare(strict_types=1);
 <?php declare(strict_types=1);
 
 
-const SOA_VALUES = [
+const NS_SOA_VALUES = [
 	'ttl' => 10800,
 	'ttl' => 10800,
 	'email' => CONF['ns']['public_soa_email'],
 	'email' => CONF['ns']['public_soa_email'],
 	'refresh' => 10800,
 	'refresh' => 10800,
@@ -9,15 +9,15 @@ const SOA_VALUES = [
 	'negative' => 10800,
 	'negative' => 10800,
 ];
 ];
 
 
-const MIN_TTL = 300;
-const DEFAULT_TTL = 10800;
-const MAX_TTL = 1728000;
+const NS_MIN_TTL = 300;
+const NS_DEFAULT_TTL = 10800;
+const NS_MAX_TTL = 1728000;
 
 
-const ALLOWED_TYPES = ['AAAA', 'A', 'TXT', 'SRV', 'MX', 'SSHFP', 'TLSA', 'NS', 'DS', 'CSYNC', 'CAA', 'CNAME', 'DNAME', 'SVCB', 'HTTPS', 'LOC'];
+const NS_ALLOWED_TYPES = ['AAAA', 'A', 'TXT', 'SRV', 'MX', 'SSHFP', 'TLSA', 'NS', 'DS', 'CSYNC', 'CAA', 'CNAME', 'DNAME', 'SVCB', 'HTTPS', 'LOC'];
 
 
-const ZONE_MAX_CHARACTERS = 10000;
+const NS_TEXTAREA_MAX_CHARACTERS = 10000;
 
 
-const SYNC_TTL = 10800;
+const NS_SYNC_TTL = 10800;
 
 
 function nsParseCommonRequirements(): array {
 function nsParseCommonRequirements(): array {
 	nsCheckZonePossession($_POST['zone']);
 	nsCheckZonePossession($_POST['zone']);
@@ -29,10 +29,10 @@ function nsParseCommonRequirements(): array {
 
 
 	$values['ttl'] = intval($_POST['ttl-value'] * $_POST['ttl-multiplier']);
 	$values['ttl'] = intval($_POST['ttl-value'] * $_POST['ttl-multiplier']);
 
 
-	if ($values['ttl'] < MIN_TTL)
-		output(403, sprintf(_('TTLs shorter than %s seconds are forbidden.'), MIN_TTL));
-	if ($values['ttl'] > MAX_TTL)
-		output(403, sprintf(_('TTLs longer than %s seconds are forbidden.'), MAX_TTL));
+	if ($values['ttl'] < NS_MIN_TTL)
+		output(403, sprintf(_('TTLs shorter than %s seconds are forbidden.'), NS_MIN_TTL));
+	if ($values['ttl'] > NS_MAX_TTL)
+		output(403, sprintf(_('TTLs longer than %s seconds are forbidden.'), NS_MAX_TTL));
 
 
 	return $values;
 	return $values;
 }
 }

+ 59 - 4
fn/reg.php

@@ -2,6 +2,9 @@
 
 
 const SUBDOMAIN_REGEX = '^(?!\-)(?!..\-\-)[a-z0-9-]{4,63}(?<!\-)$';
 const SUBDOMAIN_REGEX = '^(?!\-)(?!..\-\-)[a-z0-9-]{4,63}(?<!\-)$';
 
 
+const REG_TEXTAREA_MAX_CHARACTERS = 5000;
+const REG_ALLOWED_TYPES = ['NS', 'DS', 'AAAA', 'A'];
+
 function regListUserDomains(): array {
 function regListUserDomains(): array {
 	if (isset($_SESSION['id']))
 	if (isset($_SESSION['id']))
 		return query('select', 'registry', ['username' => $_SESSION['id']], 'domain');
 		return query('select', 'registry', ['username' => $_SESSION['id']], 'domain');
@@ -13,14 +16,16 @@ function regCheckDomainPossession(string $domain): void {
 		output(403, 'You don\'t own this domain on the registry.');
 		output(403, 'You don\'t own this domain on the registry.');
 }
 }
 
 
+function regStripDomain(string $domain, string $content): string {
+	return preg_replace('/^(?:[a-z0-9._-]+\.)?' . preg_quote($domain, '/') . '[\t ]+.+$/Dm', '', $content);
+}
+
 function regDeleteDomain(string $domain, string $user_id): void {
 function regDeleteDomain(string $domain, string $user_id): void {
 	// Delete domain from registry file
 	// Delete domain from registry file
 	$path = CONF['reg']['suffixes_path'] . '/' . regParseDomain($domain)['suffix'] . 'zone';
 	$path = CONF['reg']['suffixes_path'] . '/' . regParseDomain($domain)['suffix'] . 'zone';
-	$content = file_get_contents($path);
-	if ($content === false)
+	if (($content = file_get_contents($path)) === false)
 		output(500, 'Failed to read current registry file.');
 		output(500, 'Failed to read current registry file.');
-	$content = preg_replace('/^(?:[a-z0-9._-]+\.)?' . preg_quote($domain, '/') . '[\t ]+.+$/Dm', '', $content);
-	if (file_put_contents($path, $content) === false)
+	if (file_put_contents($path, regStripDomain($domain, $content)) === false)
 		output(500, 'Failed to write new registry file.');
 		output(500, 'Failed to write new registry file.');
 
 
 	try {
 	try {
@@ -59,3 +64,53 @@ function regParseDomain(string $domain): array {
 		'suffix' => $suffix,
 		'suffix' => $suffix,
 	];
 	];
 }
 }
+
+function regParseRecord(string $domain, array $record): array {
+	checkAbsoluteDomainFormat($record['domain']);
+
+	if ($record['domain'] !== $_POST['domain']) {
+		if ($record['type'] !== 'ip')
+			output(403, _('You can only set a NS/DS record for an apex domain.'));
+		else if (!str_ends_with($record['domain'], '.' . $domain))
+			output(403, _('You can\'t set a record for another domain.'));
+	}
+
+	$new_rec = [
+		$record['domain'],
+		CONF['reg']['ttl'],
+		$record['type'],
+	];
+	if ($record['type'] === 'DS') {
+		if (!in_array($record['algo'], ['8', '13', '14', '15', '16'], true))
+			output(403, 'Wrong value for <code>algo</code>.');
+
+		if ((preg_match('/^[0-9]{1,6}$/D', $record['keytag'])) !== 1 OR !($record['keytag'] >= 1) OR !($record['keytag'] <= 65535))
+			output(403, 'Wrong value for <code>keytag</code>.');
+
+		if ($record['dt'] !== '2' AND $record['dt'] !== '4')
+			output(403, 'Wrong value for <code>dt</code>.');
+
+		if (preg_match('/^(?:[0-9a-fA-F]{64}|[0-9a-fA-F]{96})$/D', $record['key']) !== 1)
+			output(403, 'Wrong value for <code>key</code>.');
+
+		return [
+			...$new_rec,
+			$record['keytag'],
+			$record['algo'],
+			$record['dt'],
+			$record['key'],
+		];
+	}
+	if ($record['type'] === 'NS')
+		return [
+			...$new_rec,
+			formatAbsoluteDomain($record['ns']),
+		];
+	if ($record['type'] === 'ip')
+		return [
+			$record['domain'],
+			CONF['reg']['ttl'],
+			checkIpFormat($record['ip']),
+			$record['ip'],
+		];
+}

+ 2 - 2
jobs/check.php

@@ -204,8 +204,8 @@ function testNs(string $domain): void {
 		exit('Error: /ns/caa: CAA record not set' . LF);
 		exit('Error: /ns/caa: CAA record not set' . LF);
 
 
 	curlTest('/ns/edit', [
 	curlTest('/ns/edit', [
-		'zone' => $domain,
-		'zone-content' => 'aaaa.' . $domain . ' 3600 AAAA ' . CONF['ht']['ipv6_address'] . "\r\n"
+		'domain' => $domain,
+		'records' => 'aaaa.' . $domain . ' 3600 AAAA ' . CONF['ht']['ipv6_address'] . "\r\n"
 			. '@ 86400 NS ' . CONF['ns']['servers'][0] . "\r\n",
 			. '@ 86400 NS ' . CONF['ns']['servers'][0] . "\r\n",
 	]);
 	]);
 	exescape([
 	exescape([

+ 297 - 260
locales/fr/C/LC_MESSAGES/messages.po

@@ -1,7 +1,7 @@
 msgid ""
 msgid ""
 msgstr ""
 msgstr ""
 "Report-Msgid-Bugs-To: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-07-16 20:50+0200\n"
+"POT-Creation-Date: 2023-07-31 01:03+0200\n"
 "Language: fr\n"
 "Language: fr\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 
 
@@ -13,8 +13,8 @@ msgstr "Authentification"
 msgid "Manage account"
 msgid "Manage account"
 msgstr "Gérer son compte"
 msgstr "Gérer son compte"
 
 
-#: pages.php:13 view.php:21 pg-view/auth/login.php:12
-#: pg-view/auth/register.php:1
+#: pages.php:13 view.php:22 pg-view/auth/login.php:13
+#: pg-view/auth/register.php:2
 msgid "Log in"
 msgid "Log in"
 msgstr "Se connecter"
 msgstr "Se connecter"
 
 
@@ -22,7 +22,7 @@ msgstr "Se connecter"
 msgid "Start a new navigation session with an existing account"
 msgid "Start a new navigation session with an existing account"
 msgstr "Démarrer une nouvelle session avec un compte existant"
 msgstr "Démarrer une nouvelle session avec un compte existant"
 
 
-#: pages.php:18 view.php:19
+#: pages.php:18 view.php:20
 msgid "Log out"
 msgid "Log out"
 msgstr "Se déconnecter"
 msgstr "Se déconnecter"
 
 
@@ -105,189 +105,197 @@ msgstr "Afficher les enregistrements"
 msgid "Print every record related to a domain and served by the registry"
 msgid "Print every record related to a domain and served by the registry"
 msgstr "Montrer tous les enregistrements liés à un domaine et servis par le registre"
 msgstr "Montrer tous les enregistrements liés à un domaine et servis par le registre"
 
 
-#: pages.php:67 pages.php:72 pages.php:117 pages.php:122 pages.php:127
-#: pages.php:132 pages.php:137 pages.php:142 pages.php:147 pages.php:152
-#: pages.php:157 pages.php:162
+#: pages.php:67
+msgid "Edit records"
+msgstr "Modifier des enregistrements"
+
+#: pages.php:68
+msgid "Set registry records to delegate a domain to chosen name servers"
+msgstr "Définir les enregistrements du registre pour déléguer un domaine à des serveurs de noms de son choix"
+
+#: pages.php:72 pages.php:77 pages.php:122 pages.php:127 pages.php:132
+#: pages.php:137 pages.php:142 pages.php:147 pages.php:152 pages.php:157
+#: pages.php:162 pages.php:167
 #, php-format
 #, php-format
 msgid "%s records"
 msgid "%s records"
 msgstr "Enregistrements %s"
 msgstr "Enregistrements %s"
 
 
-#: pages.php:68
+#: pages.php:73
 #, php-format
 #, php-format
 msgid "Indicate the name servers of a %s subdomain"
 msgid "Indicate the name servers of a %s subdomain"
 msgstr "Indiquer les serveurs de nom d'un sous-domaine de %s"
 msgstr "Indiquer les serveurs de nom d'un sous-domaine de %s"
 
 
-#: pages.php:73
+#: pages.php:78
 msgid "Delegate <abbr title=\"Domain Name System Security Extensions\">DNSSEC</abbr> trust"
 msgid "Delegate <abbr title=\"Domain Name System Security Extensions\">DNSSEC</abbr> trust"
 msgstr "Déléguer la confiance <abbr title=\"Domain Name System Security Extensions\">DNSSEC</abbr>"
 msgstr "Déléguer la confiance <abbr title=\"Domain Name System Security Extensions\">DNSSEC</abbr>"
 
 
-#: pages.php:77
+#: pages.php:82
 msgid "Receive a domain transfer"
 msgid "Receive a domain transfer"
 msgstr "Recevoir un transfert de domaine"
 msgstr "Recevoir un transfert de domaine"
 
 
-#: pages.php:78
+#: pages.php:83
 msgid "Transfer a domain owned by another account to the current account"
 msgid "Transfer a domain owned by another account to the current account"
 msgstr "Transférer vers le compte actuel un domaine possédé par un autre compte"
 msgstr "Transférer vers le compte actuel un domaine possédé par un autre compte"
 
 
-#: pages.php:82
+#: pages.php:87
 msgid "Glue records"
 msgid "Glue records"
 msgstr "Glue records"
 msgstr "Glue records"
 
 
-#: pages.php:83
+#: pages.php:88
 msgid "Advanced: store the IP address of a name server whose domain is inside the domain it serves"
 msgid "Advanced: store the IP address of a name server whose domain is inside the domain it serves"
 msgstr "Avancé&nbsp;: indiquer l'adresse IP d'un serveur de nom dont le domaine descend de la zone qu'il sert"
 msgstr "Avancé&nbsp;: indiquer l'adresse IP d'un serveur de nom dont le domaine descend de la zone qu'il sert"
 
 
-#: pages.php:89 pg-view/ns/index.php:24
+#: pages.php:94 pg-view/ns/index.php:25
 msgid "Name servers"
 msgid "Name servers"
 msgstr "Serveurs de nom"
 msgstr "Serveurs de nom"
 
 
-#: pages.php:90
+#: pages.php:95
 msgid "Host and manage domain's records"
 msgid "Host and manage domain's records"
 msgstr "Héberger et gérer les enregistrements d'un domaine"
 msgstr "Héberger et gérer les enregistrements d'un domaine"
 
 
-#: pages.php:93
+#: pages.php:98
 msgid "Add zone"
 msgid "Add zone"
 msgstr "Ajouter une zone"
 msgstr "Ajouter une zone"
 
 
-#: pages.php:94
+#: pages.php:99
 #, php-format
 #, php-format
 msgid "The zone will be managed by %s name servers"
 msgid "The zone will be managed by %s name servers"
 msgstr "La zone sera gérée par les serveurs de nom de %s"
 msgstr "La zone sera gérée par les serveurs de nom de %s"
 
 
-#: pages.php:98
+#: pages.php:103
 msgid "Delete zone"
 msgid "Delete zone"
 msgstr "Supprimer une zone"
 msgstr "Supprimer une zone"
 
 
-#: pages.php:99
+#: pages.php:104
 msgid "Erase all zone data"
 msgid "Erase all zone data"
 msgstr "Effacer tous les enregistrements d'une zone"
 msgstr "Effacer tous les enregistrements d'une zone"
 
 
-#: pages.php:102
+#: pages.php:107
 msgid "Display zone"
 msgid "Display zone"
 msgstr "Afficher une zone"
 msgstr "Afficher une zone"
 
 
-#: pages.php:103
+#: pages.php:108
 msgid "Print zonefile content"
 msgid "Print zonefile content"
 msgstr "Montrer le contenu d'un fichier de zone"
 msgstr "Montrer le contenu d'un fichier de zone"
 
 
-#: pages.php:107
+#: pages.php:112
 msgid "Edit zone"
 msgid "Edit zone"
 msgstr "Modifier une zone"
 msgstr "Modifier une zone"
 
 
-#: pages.php:108
+#: pages.php:113
 msgid "Change zonefile content"
 msgid "Change zonefile content"
 msgstr "Éditer le contenu d'un fichier de zone"
 msgstr "Éditer le contenu d'un fichier de zone"
 
 
-#: pages.php:112
+#: pages.php:117
 msgid "AAAA and A records"
 msgid "AAAA and A records"
 msgstr "Enregistrements AAAA et A"
 msgstr "Enregistrements AAAA et A"
 
 
-#: pages.php:113
+#: pages.php:118
 msgid "Store domain's IP address"
 msgid "Store domain's IP address"
 msgstr "Indiquer l'adresse IP d'un domaine"
 msgstr "Indiquer l'adresse IP d'un domaine"
 
 
-#: pages.php:118
+#: pages.php:123
 msgid "Store zone's name server"
 msgid "Store zone's name server"
 msgstr "Indiquer les serveurs de nom d'une zone"
 msgstr "Indiquer les serveurs de nom d'une zone"
 
 
-#: pages.php:123
+#: pages.php:128
 msgid "Associate text to domain"
 msgid "Associate text to domain"
 msgstr "Associer du texte à un domaine"
 msgstr "Associer du texte à un domaine"
 
 
-#: pages.php:128
+#: pages.php:133
 msgid "Limit the certificate authorities allowed to certify the domain"
 msgid "Limit the certificate authorities allowed to certify the domain"
 msgstr "Limiter les autorités de certification autorisées à certifier un domaine"
 msgstr "Limiter les autorités de certification autorisées à certifier un domaine"
 
 
-#: pages.php:133
+#: pages.php:138
 msgid "Store the location of a domain's service"
 msgid "Store the location of a domain's service"
 msgstr "Indiquer l'adresse exacte d'un service pour un domaine"
 msgstr "Indiquer l'adresse exacte d'un service pour un domaine"
 
 
-#: pages.php:138
+#: pages.php:143
 msgid "Store the email server's address"
 msgid "Store the email server's address"
 msgstr "Indiquer l'adresse d'un serveur de courriels"
 msgstr "Indiquer l'adresse d'un serveur de courriels"
 
 
-#: pages.php:143
+#: pages.php:148
 msgid "Store <abbr title=\"Secure SHell\">SSH</abbr> public keys fingerprints"
 msgid "Store <abbr title=\"Secure SHell\">SSH</abbr> public keys fingerprints"
 msgstr "Indiquer les empreintes de clés publiques <abbr title=\"Secure SHell\">SSH</abbr>"
 msgstr "Indiquer les empreintes de clés publiques <abbr title=\"Secure SHell\">SSH</abbr>"
 
 
-#: pages.php:148
+#: pages.php:153
 msgid "Setup <abbr title=\"DNS-based Authentication of Named Entities\">DANE</abbr> by publishing the <abbr title=\"Transport Layer Security\">TLS</abbr> certificate fingerprint"
 msgid "Setup <abbr title=\"DNS-based Authentication of Named Entities\">DANE</abbr> by publishing the <abbr title=\"Transport Layer Security\">TLS</abbr> certificate fingerprint"
 msgstr "Mettre en place <abbr title=\"DNS-based Authentication of Named Entities\">DANE</abbr> et publiant l'empreinte d'un certificat <abbr title=\"Transport Layer Security\">TLS</abbr>"
 msgstr "Mettre en place <abbr title=\"DNS-based Authentication of Named Entities\">DANE</abbr> et publiant l'empreinte d'un certificat <abbr title=\"Transport Layer Security\">TLS</abbr>"
 
 
-#: pages.php:153
+#: pages.php:158
 msgid "Define a domain as an alias of another"
 msgid "Define a domain as an alias of another"
 msgstr "Définir un domaine comme étant l'alias d'un autre"
 msgstr "Définir un domaine comme étant l'alias d'un autre"
 
 
-#: pages.php:158
+#: pages.php:163
 msgid "Define all subdomains of a domain as aliases of subdomains of another domain"
 msgid "Define all subdomains of a domain as aliases of subdomains of another domain"
 msgstr "Définir la descendance d'un domaine comme alias de la descendance d'un autre domaine"
 msgstr "Définir la descendance d'un domaine comme alias de la descendance d'un autre domaine"
 
 
-#: pages.php:163
+#: pages.php:168
 msgid "Store geographic coordinates"
 msgid "Store geographic coordinates"
 msgstr "Indiquer des coordonnées géographiques"
 msgstr "Indiquer des coordonnées géographiques"
 
 
-#: pages.php:167
+#: pages.php:172
 #, php-format
 #, php-format
 msgid "Synchronized records"
 msgid "Synchronized records"
 msgstr "Enregistrements synchronisés"
 msgstr "Enregistrements synchronisés"
 
 
-#: pages.php:168
+#: pages.php:173
 msgid "Regularly fetch distant records and update them to a local zone"
 msgid "Regularly fetch distant records and update them to a local zone"
 msgstr "Récupérer régulièrement des enregistrements distants et les mettre à jour vers une zone locale"
 msgstr "Récupérer régulièrement des enregistrements distants et les mettre à jour vers une zone locale"
 
 
-#: pages.php:174
+#: pages.php:179
 msgid "Web"
 msgid "Web"
 msgstr "Web"
 msgstr "Web"
 
 
-#: pages.php:175
+#: pages.php:180
 msgid "Upload a static website into an <abbr title=\"SSH File Transfer Protocol\">SFTP</abbr> space"
 msgid "Upload a static website into an <abbr title=\"SSH File Transfer Protocol\">SFTP</abbr> space"
 msgstr "Téléverser un site statique dans un espace <abbr title=\"SSH File Transfert Protocol\">SFTP</abbr>"
 msgstr "Téléverser un site statique dans un espace <abbr title=\"SSH File Transfert Protocol\">SFTP</abbr>"
 
 
-#: pages.php:178
+#: pages.php:183
 #, php-format
 #, php-format
 msgid "%s subpath access"
 msgid "%s subpath access"
 msgstr "Accès par sous-chemin de %s"
 msgstr "Accès par sous-chemin de %s"
 
 
-#: pages.php:179 pages.php:184 pages.php:189
+#: pages.php:184 pages.php:189 pages.php:194
 #, php-format
 #, php-format
 msgid "Its URL will look like %s"
 msgid "Its URL will look like %s"
 msgstr "Son URL ressemblera à %s"
 msgstr "Son URL ressemblera à %s"
 
 
-#: pages.php:179 pages.php:184 pages.php:189
+#: pages.php:184 pages.php:189 pages.php:194
 msgid "mysite"
 msgid "mysite"
 msgstr "monsite"
 msgstr "monsite"
 
 
-#: pages.php:183
+#: pages.php:188
 #, php-format
 #, php-format
 msgid "%s subdomain access"
 msgid "%s subdomain access"
 msgstr "Accès par sous-domaine de %s"
 msgstr "Accès par sous-domaine de %s"
 
 
-#: pages.php:188
+#: pages.php:193
 msgid "Dedicated domain with Let's Encrypt certificate access"
 msgid "Dedicated domain with Let's Encrypt certificate access"
 msgstr "Accès par domaine dédié avec certificat Let's Encrypt"
 msgstr "Accès par domaine dédié avec certificat Let's Encrypt"
 
 
-#: pages.php:193
+#: pages.php:198
 msgid "Onion service access"
 msgid "Onion service access"
 msgstr "Accès par service Onion"
 msgstr "Accès par service Onion"
 
 
-#: pages.php:194
+#: pages.php:199
 #, php-format
 #, php-format
 msgid "Its URL will look like %s, and work only through the Tor network"
 msgid "Its URL will look like %s, and work only through the Tor network"
 msgstr "Son URL ressemblera à %s, et ne fonctionnera que par le réseau Tor"
 msgstr "Son URL ressemblera à %s, et ne fonctionnera que par le réseau Tor"
 
 
-#: pages.php:198 pg-view/ht/del.php:18
+#: pages.php:203 pg-view/ht/del.php:19
 msgid "Delete access"
 msgid "Delete access"
 msgstr "Supprimer un accès"
 msgstr "Supprimer un accès"
 
 
-#: pages.php:199
+#: pages.php:204
 msgid "Delete an existing HTTP access from a subdirectory of the SFTP space"
 msgid "Delete an existing HTTP access from a subdirectory of the SFTP space"
 msgstr "Retirer un accès HTTP existant d'un sous-dossier de l'espace SFTP"
 msgstr "Retirer un accès HTTP existant d'un sous-dossier de l'espace SFTP"
 
 
-#: pages.php:202
+#: pages.php:207
 msgid "Manage SSH keys"
 msgid "Manage SSH keys"
 msgstr "Gérer les clés SSH"
 msgstr "Gérer les clés SSH"
 
 
-#: pages.php:203
+#: pages.php:208
 msgid "Choose what SSH key can edit what directory"
 msgid "Choose what SSH key can edit what directory"
 msgstr "Choisir quelle clé SSH peut modifier quel dossier"
 msgstr "Choisir quelle clé SSH peut modifier quel dossier"
 
 
@@ -295,7 +303,7 @@ msgstr "Choisir quelle clé SSH peut modifier quel dossier"
 msgid "This account doesn't exist anymore. Log out to end this ghost session."
 msgid "This account doesn't exist anymore. Log out to end this ghost session."
 msgstr "Ce compte n'existe plus. Déconnectez-vous pour terminer cette session fantôme."
 msgstr "Ce compte n'existe plus. Déconnectez-vous pour terminer cette session fantôme."
 
 
-#: router.php:106 view.php:39
+#: router.php:106 view.php:40
 msgid "This service is currently under maintenance. No action can be taken on it until an administrator finishes repairing it."
 msgid "This service is currently under maintenance. No action can be taken on it until an administrator finishes repairing it."
 msgstr "Ce service est en cours de maintenance. Aucune action ne peut être effectuée avant qu'ane administrataire termine de le réparer."
 msgstr "Ce service est en cours de maintenance. Aucune action ne peut être effectuée avant qu'ane administrataire termine de le réparer."
 
 
@@ -303,24 +311,24 @@ msgstr "Ce service est en cours de maintenance. Aucune action ne peut être effe
 msgid "You need to be logged in to do this."
 msgid "You need to be logged in to do this."
 msgstr "Vous devez être connecté·e à un compte pour faire cela."
 msgstr "Vous devez être connecté·e à un compte pour faire cela."
 
 
-#: view.php:19
+#: view.php:20
 msgid "You are using a testing account. It may be deleted anytime."
 msgid "You are using a testing account. It may be deleted anytime."
 msgstr "Vous utilisez un compte de test. Il risque d'être supprimé n'importe quand."
 msgstr "Vous utilisez un compte de test. Il risque d'être supprimé n'importe quand."
 
 
-#: view.php:19
+#: view.php:20
 msgid "Read more"
 msgid "Read more"
 msgstr "En savoir plus"
 msgstr "En savoir plus"
 
 
-#: view.php:21
+#: view.php:22
 msgid "Anonymous"
 msgid "Anonymous"
 msgstr "Anonyme"
 msgstr "Anonyme"
 
 
-#: view.php:44
+#: view.php:45
 #, php-format
 #, php-format
 msgid "This form won't be accepted because you need to %slog in%s first."
 msgid "This form won't be accepted because you need to %slog in%s first."
 msgstr "Ce formulaire ne sera pas accepté car il faut %sse connecter%s d'abord."
 msgstr "Ce formulaire ne sera pas accepté car il faut %sse connecter%s d'abord."
 
 
-#: view.php:51
+#: view.php:52
 #, php-format
 #, php-format
 msgid "%sSource code%s available under %s."
 msgid "%sSource code%s available under %s."
 msgstr "%sCode source%s disponible sous %s."
 msgstr "%sCode source%s disponible sous %s."
@@ -354,7 +362,7 @@ msgstr "<strong>Erreur du serveur</strong>&nbsp;: "
 msgid "Wrong proof."
 msgid "Wrong proof."
 msgstr "Preuve incorrecte."
 msgstr "Preuve incorrecte."
 
 
-#: fn/dns.php:77
+#: fn/dns.php:76
 msgid "IP address malformed."
 msgid "IP address malformed."
 msgstr "Adresse IP malformée."
 msgstr "Adresse IP malformée."
 
 
@@ -362,17 +370,25 @@ msgstr "Adresse IP malformée."
 msgid "Domain malformed."
 msgid "Domain malformed."
 msgstr "Domaine malformé."
 msgstr "Domaine malformé."
 
 
-#: fn/ns.php:33 pg-act/ns/edit.php:25
+#: fn/ns.php:33 pg-act/ns/edit.php:27
 #, php-format
 #, php-format
 msgid "TTLs shorter than %s seconds are forbidden."
 msgid "TTLs shorter than %s seconds are forbidden."
 msgstr "Les TTLs plus courts que %s secondes sont interdits."
 msgstr "Les TTLs plus courts que %s secondes sont interdits."
 
 
-#: fn/ns.php:35 pg-act/ns/edit.php:27
+#: fn/ns.php:35 pg-act/ns/edit.php:29
 #, php-format
 #, php-format
 msgid "TTLs longer than %s seconds are forbidden."
 msgid "TTLs longer than %s seconds are forbidden."
 msgstr "Les TTLs plus longs que %s secondes sont interdits."
 msgstr "Les TTLs plus longs que %s secondes sont interdits."
 
 
-#: pg-view/index.php:3
+#: fn/reg.php:73
+msgid "You can only set a NS/DS record for an apex domain."
+msgstr "Vous pouvez seulement définir un enregistrement NS/DS à l'apex du domaine."
+
+#: fn/reg.php:75
+msgid "You can't set a record for another domain."
+msgstr "Vous ne pouvez pas définir un enregistrement pour un autre domaine."
+
+#: pg-view/index.php:4
 msgid "About this installation"
 msgid "About this installation"
 msgstr "À propos de cette installation"
 msgstr "À propos de cette installation"
 
 
@@ -405,7 +421,7 @@ msgstr "Clé de passe actuelle incorrecte."
 msgid "Password updated."
 msgid "Password updated."
 msgstr "Clé de passe mise à jour."
 msgstr "Clé de passe mise à jour."
 
 
-#: pg-act/auth/register.php:4 pg-view/auth/register.php:3
+#: pg-act/auth/register.php:4 pg-view/auth/register.php:4
 msgid "Registrations are currently closed on this installation."
 msgid "Registrations are currently closed on this installation."
 msgstr "Les inscriptions sont actuellement fermées sur cette installation."
 msgstr "Les inscriptions sont actuellement fermées sur cette installation."
 
 
@@ -485,28 +501,28 @@ msgstr "Clés SSH mises à jour."
 #: pg-act/ns/caa.php:25 pg-act/ns/cname.php:16 pg-act/ns/dname.php:16
 #: pg-act/ns/caa.php:25 pg-act/ns/cname.php:16 pg-act/ns/dname.php:16
 #: pg-act/ns/ip.php:16 pg-act/ns/loc.php:72 pg-act/ns/mx.php:20
 #: pg-act/ns/ip.php:16 pg-act/ns/loc.php:72 pg-act/ns/mx.php:20
 #: pg-act/ns/ns.php:16 pg-act/ns/srv.php:28 pg-act/ns/sshfp.php:25
 #: pg-act/ns/ns.php:16 pg-act/ns/srv.php:28 pg-act/ns/sshfp.php:25
-#: pg-act/ns/tlsa.php:29 pg-act/ns/txt.php:17 pg-act/reg/ds.php:30
-#: pg-act/reg/glue.php:14 pg-act/reg/ns.php:14
+#: pg-act/ns/tlsa.php:29 pg-act/ns/txt.php:17 pg-act/reg/ds.php:12
+#: pg-act/reg/glue.php:13 pg-act/reg/ns.php:12
 msgid "Modification done."
 msgid "Modification done."
 msgstr "Modification effectuée."
 msgstr "Modification effectuée."
 
 
-#: pg-act/ns/edit.php:17
+#: pg-act/ns/edit.php:19 pg-act/reg/edit.php:14
 #, php-format
 #, php-format
 msgid "The zone is limited to %s characters."
 msgid "The zone is limited to %s characters."
 msgstr "La zone est limitée à %s caractères."
 msgstr "La zone est limitée à %s caractères."
 
 
-#: pg-act/ns/edit.php:21
+#: pg-act/ns/edit.php:23 pg-act/reg/edit.php:18
 msgid "The following line does not match the expected format: "
 msgid "The following line does not match the expected format: "
 msgstr "La ligne suivante ne correspond pas au format attendu&nbsp;: "
 msgstr "La ligne suivante ne correspond pas au format attendu&nbsp;: "
 
 
-#: pg-act/ns/edit.php:23
+#: pg-act/ns/edit.php:25 pg-act/reg/edit.php:20 pg-act/reg/edit.php:28
 #, php-format
 #, php-format
 msgid "The %s type is not allowed."
 msgid "The %s type is not allowed."
 msgstr "Le type %s n'est pas autorisé."
 msgstr "Le type %s n'est pas autorisé."
 
 
-#: pg-act/ns/edit.php:38
-msgid "Sent zone content is not correct (according to <code>kzonecheck</code>)."
-msgstr "Le contenu de zone envoyé n'est pas correct (selon <code>kzonecheck</code>)."
+#: pg-act/ns/edit.php:40 pg-act/reg/edit.php:51
+msgid "Sent content is not correct (according to <code>kzonecheck</code>)."
+msgstr "Le contenu envoyé n'est pas correct (selon <code>kzonecheck</code>)."
 
 
 #: pg-act/ns/sync.php:19
 #: pg-act/ns/sync.php:19
 msgid "Multiple source domains can't be applied to the same target domain."
 msgid "Multiple source domains can't be applied to the same target domain."
@@ -536,6 +552,10 @@ msgstr "Zone créée."
 msgid "Zone deleted."
 msgid "Zone deleted."
 msgstr "Zone supprimée."
 msgstr "Zone supprimée."
 
 
+#: pg-act/reg/edit.php:22
+msgid "A DS record expects 4 arguments."
+msgstr "Un enregistrement DS attends 4 arguments."
+
 #: pg-act/reg/register.php:4 pg-act/reg/transfer.php:4
 #: pg-act/reg/register.php:4 pg-act/reg/transfer.php:4
 msgid "This format of subdomain is not allowed."
 msgid "This format of subdomain is not allowed."
 msgstr "Ce format de sous-domaine n'est pas autorisé."
 msgstr "Ce format de sous-domaine n'est pas autorisé."
@@ -584,705 +604,722 @@ msgstr "Le domaine a été transféré vers le compte actuel ; l'enregistrement
 msgid "Domain unregistered."
 msgid "Domain unregistered."
 msgstr "Domaine désenregistré."
 msgstr "Domaine désenregistré."
 
 
-#: pg-view/auth/approval.php:2
+#: pg-view/auth/approval.php:3
 msgid "This form allows to use an approval key to validate your account. Approval keys are distributed by an administrator upon request."
 msgid "This form allows to use an approval key to validate your account. Approval keys are distributed by an administrator upon request."
 msgstr "Ce formulaire permet d'utiliser une clé d'approbation pour valider son compte. Les clés d'approbation sont distribuées par ane administrataire sur demande."
 msgstr "Ce formulaire permet d'utiliser une clé d'approbation pour valider son compte. Les clés d'approbation sont distribuées par ane administrataire sur demande."
 
 
-#: pg-view/auth/approval.php:6
+#: pg-view/auth/approval.php:7
 msgid "Approval key"
 msgid "Approval key"
 msgstr "Clé d'approbation"
 msgstr "Clé d'approbation"
 
 
-#: pg-view/auth/approval.php:9
+#: pg-view/auth/approval.php:10
 msgid "Use for this account"
 msgid "Use for this account"
 msgstr "Utiliser pour ce compte"
 msgstr "Utiliser pour ce compte"
 
 
-#: pg-view/auth/index.php:3
+#: pg-view/auth/index.php:4
 msgid "Account type"
 msgid "Account type"
 msgstr "Type de compte"
 msgstr "Type de compte"
 
 
-#: pg-view/auth/index.php:9
+#: pg-view/auth/index.php:10
 msgid "You are currently using a <strong>testing</strong> account."
 msgid "You are currently using a <strong>testing</strong> account."
 msgstr "Vous utilisez actuellement un compte <strong>de test</strong>."
 msgstr "Vous utilisez actuellement un compte <strong>de test</strong>."
 
 
-#: pg-view/auth/index.php:10
+#: pg-view/auth/index.php:11
 msgid "You are currently using an <strong>approved</strong> account."
 msgid "You are currently using an <strong>approved</strong> account."
 msgstr "Vous utilisez actuellement un compte <strong>approuvé</strong>."
 msgstr "Vous utilisez actuellement un compte <strong>approuvé</strong>."
 
 
-#: pg-view/auth/index.php:13
+#: pg-view/auth/index.php:14
 msgid "You are not logged in."
 msgid "You are not logged in."
 msgstr "Vous n'êtes connecté·e à aucun compte."
 msgstr "Vous n'êtes connecté·e à aucun compte."
 
 
-#: pg-view/auth/index.php:18
+#: pg-view/auth/index.php:19
 msgid "When an account is created, it's a <em>testing</em> account. A testing account is only temporary and with limited capabilities on the services. Once the account is validated by using an approval key requested to an administrator, it becomes an <em>approved</em> account."
 msgid "When an account is created, it's a <em>testing</em> account. A testing account is only temporary and with limited capabilities on the services. Once the account is validated by using an approval key requested to an administrator, it becomes an <em>approved</em> account."
 msgstr "Quand un compte est créé, c'est un compte <em>de test</em>. Un compte de test est seulement temporaire et avec des capacités restreintes sur les services. Une fois le compte validé en utilisant une clé d'approbation demandée à ane administrataire, il devient un compte <em>approuvé</em>."
 msgstr "Quand un compte est créé, c'est un compte <em>de test</em>. Un compte de test est seulement temporaire et avec des capacités restreintes sur les services. Une fois le compte validé en utilisant une clé d'approbation demandée à ane administrataire, il devient un compte <em>approuvé</em>."
 
 
-#: pg-view/auth/index.php:21
+#: pg-view/auth/index.php:22
 msgid "Rate limit"
 msgid "Rate limit"
 msgstr "Limite de débit"
 msgstr "Limite de débit"
 
 
-#: pg-view/auth/index.php:25
+#: pg-view/auth/index.php:26
 #, php-format
 #, php-format
 msgid "Your account is at %s%% of the rate limit."
 msgid "Your account is at %s%% of the rate limit."
 msgstr "Votre compte est à %s%% de la limite de débit."
 msgstr "Votre compte est à %s%% de la limite de débit."
 
 
-#: pg-view/auth/index.php:27
+#: pg-view/auth/index.php:28
 msgid "Most of the form submissions bring you closer to the rate limit. If you reach it, you need to wait in order to be able to submit forms again."
 msgid "Most of the form submissions bring you closer to the rate limit. If you reach it, you need to wait in order to be able to submit forms again."
 msgstr "La plupart des traitements de formulaires vous rapprochent de la limite de débit. Si vous l'atteignez, vous devez attendre avant de pouvoir envoyer des formulaires à nouveau."
 msgstr "La plupart des traitements de formulaires vous rapprochent de la limite de débit. Si vous l'atteignez, vous devez attendre avant de pouvoir envoyer des formulaires à nouveau."
 
 
-#: pg-view/auth/index.php:31
+#: pg-view/auth/index.php:32
 msgid "Internal ID"
 msgid "Internal ID"
 msgstr "Identifiant interne"
 msgstr "Identifiant interne"
 
 
-#: pg-view/auth/index.php:33
+#: pg-view/auth/index.php:34
 #, php-format
 #, php-format
 msgid "The current account's internal ID is %s."
 msgid "The current account's internal ID is %s."
 msgstr "L'identifiant interne du compte actuel est %s."
 msgstr "L'identifiant interne du compte actuel est %s."
 
 
-#: pg-view/auth/login.php:1
+#: pg-view/auth/login.php:2
 msgid "New?"
 msgid "New?"
 msgstr "Nouvele ?"
 msgstr "Nouvele ?"
 
 
-#: pg-view/auth/login.php:1 pg-view/auth/register.php:16
+#: pg-view/auth/login.php:2 pg-view/auth/register.php:17
 msgid "Create an account"
 msgid "Create an account"
 msgstr "Créer un compte"
 msgstr "Créer un compte"
 
 
-#: pg-view/auth/login.php:4 pg-view/auth/register.php:6 pg-view/ht/index.php:64
+#: pg-view/auth/login.php:5 pg-view/auth/register.php:7 pg-view/ht/index.php:65
 msgid "Username"
 msgid "Username"
 msgstr "Identifiant"
 msgstr "Identifiant"
 
 
-#: pg-view/auth/login.php:8 pg-view/auth/register.php:11
-#: pg-view/ht/index.php:68
+#: pg-view/auth/login.php:9 pg-view/auth/register.php:12
+#: pg-view/ht/index.php:69
 msgid "Password"
 msgid "Password"
 msgstr "Clé de passe"
 msgstr "Clé de passe"
 
 
-#: pg-view/auth/password.php:2 pg-view/auth/unregister.php:6
-#: pg-view/auth/username.php:2
+#: pg-view/auth/password.php:3 pg-view/auth/unregister.php:7
+#: pg-view/auth/username.php:3
 msgid "Current password"
 msgid "Current password"
 msgstr "Clé de passe actuelle"
 msgstr "Clé de passe actuelle"
 
 
-#: pg-view/auth/password.php:5
+#: pg-view/auth/password.php:6
 msgid "New password"
 msgid "New password"
 msgstr "Nouvelle clé de passe"
 msgstr "Nouvelle clé de passe"
 
 
-#: pg-view/auth/password.php:8
+#: pg-view/auth/password.php:9
 msgid "Update password"
 msgid "Update password"
 msgstr "Mettre à jour la clé de passe"
 msgstr "Mettre à jour la clé de passe"
 
 
-#: pg-view/auth/register.php:1
+#: pg-view/auth/register.php:2
 msgid "Already have an account?"
 msgid "Already have an account?"
 msgstr "Déjà un compte ?"
 msgstr "Déjà un compte ?"
 
 
-#: pg-view/auth/register.php:12
+#: pg-view/auth/register.php:13
 #, php-format
 #, php-format
 msgid "Minimum %1$s characters, or %2$s characters if it contains lowercase, uppercase and digit."
 msgid "Minimum %1$s characters, or %2$s characters if it contains lowercase, uppercase and digit."
 msgstr "Minimum %1$s caractères, ou %2$s caractères si elle contient minuscule, majuscule et chiffre."
 msgstr "Minimum %1$s caractères, ou %2$s caractères si elle contient minuscule, majuscule et chiffre."
 
 
-#: pg-view/auth/unregister.php:2
+#: pg-view/auth/unregister.php:3
 msgid "This will delete every resource managed by the current account, including registered domains, hosted DNS records, websites files and cryptographic keys for Onion services and DNSSEC."
 msgid "This will delete every resource managed by the current account, including registered domains, hosted DNS records, websites files and cryptographic keys for Onion services and DNSSEC."
 msgstr "Ceci supprimera toutes les ressources gérées par le compte actuel, y compris les domaines enregistrés, les enregistrements DNS hébergés, les fichiers des sites et les clés cryptographiques des services Onion et de DNSSEC."
 msgstr "Ceci supprimera toutes les ressources gérées par le compte actuel, y compris les domaines enregistrés, les enregistrements DNS hébergés, les fichiers des sites et les clés cryptographiques des services Onion et de DNSSEC."
 
 
-#: pg-view/auth/unregister.php:10
+#: pg-view/auth/unregister.php:11
 msgid "Delete the current account and everything related (required)"
 msgid "Delete the current account and everything related (required)"
 msgstr "Supprimer le compte actuel et tout ce qui y est lié (requis)"
 msgstr "Supprimer le compte actuel et tout ce qui y est lié (requis)"
 
 
-#: pg-view/auth/unregister.php:12 pg-view/ns/form.ns.php:4 pg-view/reg/ds.php:5
-#: pg-view/reg/glue.php:5 pg-view/reg/ns.php:5
+#: pg-view/auth/unregister.php:13 pg-view/ns/form.ns.php:5
+#: pg-view/reg/select-action.inc.php:5
 msgid "Delete"
 msgid "Delete"
 msgstr "Supprimer"
 msgstr "Supprimer"
 
 
-#: pg-view/auth/username.php:5
+#: pg-view/auth/username.php:6
 msgid "New username"
 msgid "New username"
 msgstr "Nouvel identifiant"
 msgstr "Nouvel identifiant"
 
 
-#: pg-view/auth/username.php:8
+#: pg-view/auth/username.php:9
 msgid "Update username"
 msgid "Update username"
 msgstr "Mettre à jour l'identifiant"
 msgstr "Mettre à jour l'identifiant"
 
 
-#: pg-view/ht/add-dns.php:2
+#: pg-view/ht/add-dns.php:3
 msgid "A Let's Encrypt certificate will be obtained."
 msgid "A Let's Encrypt certificate will be obtained."
 msgstr "Un certificat Let's Encrypt sera obtenu."
 msgstr "Un certificat Let's Encrypt sera obtenu."
 
 
-#: pg-view/ht/add-dns.php:6
+#: pg-view/ht/add-dns.php:7
 msgid "The domain must have the following records when the form is being processed."
 msgid "The domain must have the following records when the form is being processed."
 msgstr "Le domaine doit avoir les enregistrements suivants pendant le traitement du formulaire."
 msgstr "Le domaine doit avoir les enregistrements suivants pendant le traitement du formulaire."
 
 
-#: pg-view/ht/add-dns.php:29 pg-view/ns/form.ns.php:8 pg-view/ns/print.php:32
-#: pg-view/ns/zone-add.php:6 pg-view/reg/ds.php:8 pg-view/reg/glue.php:8
-#: pg-view/reg/glue.php:15 pg-view/reg/ns.php:8 pg-view/reg/print.php:2
-#: pg-view/reg/print.php:16 pg-view/reg/register.php:11
-#: pg-view/reg/unregister.php:6
+#: pg-view/ht/add-dns.php:30 pg-view/ns/form.ns.php:9 pg-view/ns/print.php:33
+#: pg-view/ns/zone-add.php:7 pg-view/reg/glue.php:5 pg-view/reg/print.php:10
+#: pg-view/reg/register.php:12 pg-view/reg/select-domain.inc.php:2
+#: pg-view/reg/unregister.php:7
 msgid "Domain"
 msgid "Domain"
 msgstr "Domaine"
 msgstr "Domaine"
 
 
-#: pg-view/ht/add-dns.php:31 pg-view/ht/add-onion.php:2
-#: pg-view/ht/add-subdomain.php:8 pg-view/ht/add-subpath.php:8
+#: pg-view/ht/add-dns.php:32 pg-view/ht/add-onion.php:3
+#: pg-view/ht/add-subdomain.php:9 pg-view/ht/add-subpath.php:9
 msgid "Target directory"
 msgid "Target directory"
 msgstr "Dossier ciblé"
 msgstr "Dossier ciblé"
 
 
-#: pg-view/ht/add-dns.php:40 pg-view/ht/add-onion.php:11
-#: pg-view/ht/add-subdomain.php:17 pg-view/ht/add-subpath.php:17
+#: pg-view/ht/add-dns.php:41 pg-view/ht/add-onion.php:12
+#: pg-view/ht/add-subdomain.php:18 pg-view/ht/add-subpath.php:18
 msgid "Setup access"
 msgid "Setup access"
 msgstr "Créer l'accès"
 msgstr "Créer l'accès"
 
 
-#: pg-view/ht/add-subdomain.php:2 pg-view/reg/register.php:6
+#: pg-view/ht/add-subdomain.php:3 pg-view/reg/register.php:7
 #, php-format
 #, php-format
 msgid "The subdomain can only contain %1$s, %2$s and %3$s, and must be between 4 and 63 characters. It can't have an hyphen (%3$s) in first, last or both third and fourth position."
 msgid "The subdomain can only contain %1$s, %2$s and %3$s, and must be between 4 and 63 characters. It can't have an hyphen (%3$s) in first, last or both third and fourth position."
 msgstr "Le sous-domain peut uniquement contenir %1$s, %2$s et %3$s, et doit être entre 4 et 63 caractères. Il ne peut pas avoir un tiret (%3$s) en première, dernière ou à la fois troisième et quatrième position."
 msgstr "Le sous-domain peut uniquement contenir %1$s, %2$s et %3$s, et doit être entre 4 et 63 caractères. Il ne peut pas avoir un tiret (%3$s) en première, dernière ou à la fois troisième et quatrième position."
 
 
-#: pg-view/ht/add-subdomain.php:6 pg-view/ns/form.ns.php:10
-#: pg-view/reg/glue.php:10 pg-view/reg/register.php:13
-#: pg-view/reg/transfer.php:9
+#: pg-view/ht/add-subdomain.php:7 pg-view/ns/form.ns.php:11
+#: pg-view/reg/glue.php:7 pg-view/reg/register.php:14
+#: pg-view/reg/transfer.php:10
 msgid "Subdomain"
 msgid "Subdomain"
 msgstr "Sous-domaine"
 msgstr "Sous-domaine"
 
 
-#: pg-view/ht/add-subpath.php:2
+#: pg-view/ht/add-subpath.php:3
 #, php-format
 #, php-format
 msgid "The path can only contain %1$s, %2$s and %3$s, and must be between 4 and 63 characters."
 msgid "The path can only contain %1$s, %2$s and %3$s, and must be between 4 and 63 characters."
 msgstr "Le chemin peut uniquement contenir %1$s, %2$s et %3$s, et doit être entre 4 et 63 caractères."
 msgstr "Le chemin peut uniquement contenir %1$s, %2$s et %3$s, et doit être entre 4 et 63 caractères."
 
 
-#: pg-view/ht/add-subpath.php:6
+#: pg-view/ht/add-subpath.php:7
 msgid "Path"
 msgid "Path"
 msgstr "Chemin"
 msgstr "Chemin"
 
 
-#: pg-view/ht/del.php:2
+#: pg-view/ht/del.php:3
 msgid "Access to delete"
 msgid "Access to delete"
 msgstr "Accès à retirer"
 msgstr "Accès à retirer"
 
 
-#: pg-view/ht/del.php:13
+#: pg-view/ht/del.php:14
 #, php-format
 #, php-format
 msgid "%1$s to %2$s"
 msgid "%1$s to %2$s"
 msgstr "%1$s vers %2$s"
 msgstr "%1$s vers %2$s"
 
 
-#: pg-view/ht/index.php:2
+#: pg-view/ht/index.php:3
 msgid "This service allows you to send files on the server using SFTP, and to make them publicly available with HTTP."
 msgid "This service allows you to send files on the server using SFTP, and to make them publicly available with HTTP."
 msgstr "Ce service permet d'envoyer des fichiers sur le serveur par SFTP, et de les rendre publiquement accessibles par HTTP."
 msgstr "Ce service permet d'envoyer des fichiers sur le serveur par SFTP, et de les rendre publiquement accessibles par HTTP."
 
 
-#: pg-view/ht/index.php:8
+#: pg-view/ht/index.php:9
 msgid "Currently hosted sites"
 msgid "Currently hosted sites"
 msgstr "Sites actuellement hébergés"
 msgstr "Sites actuellement hébergés"
 
 
-#: pg-view/ht/index.php:38
+#: pg-view/ht/index.php:39
 msgid "Adding a site access"
 msgid "Adding a site access"
 msgstr "Ajouter un accès de site"
 msgstr "Ajouter un accès de site"
 
 
-#: pg-view/ht/index.php:40
+#: pg-view/ht/index.php:41
 #, php-format
 #, php-format
 msgid "In order to be able to set up an HTTP site with this service, a subdirectory for this site must be created inside the SFTP space first. The name of this subdirectory can only contain %1$s, %2$s, %3$s, %4$s and %5$s."
 msgid "In order to be able to set up an HTTP site with this service, a subdirectory for this site must be created inside the SFTP space first. The name of this subdirectory can only contain %1$s, %2$s, %3$s, %4$s and %5$s."
 msgstr "Pour pouvoir créer un site HTTP avec ce service, un sous-dossier pour ce site doit d'abord être créé dans l'espace SFTP. Le nom de ce sous-dossier ne peut contenir que %1$s, %2$s, %3$s, %4$s et %5$s."
 msgstr "Pour pouvoir créer un site HTTP avec ce service, un sous-dossier pour ce site doit d'abord être créé dans l'espace SFTP. Le nom de ce sous-dossier ne peut contenir que %1$s, %2$s, %3$s, %4$s et %5$s."
 
 
-#: pg-view/ht/index.php:44
+#: pg-view/ht/index.php:45
 msgid "Connecting to the SFTP server"
 msgid "Connecting to the SFTP server"
 msgstr "Se connecter au serveur SFTP"
 msgstr "Se connecter au serveur SFTP"
 
 
-#: pg-view/ht/index.php:52
+#: pg-view/ht/index.php:53
 msgid "Server"
 msgid "Server"
 msgstr "Serveur"
 msgstr "Serveur"
 
 
-#: pg-view/ht/index.php:56 pg-view/ns/srv.php:16
+#: pg-view/ht/index.php:57 pg-view/ns/srv.php:17
 msgid "Port"
 msgid "Port"
 msgstr "Port"
 msgstr "Port"
 
 
-#: pg-view/ht/index.php:60
+#: pg-view/ht/index.php:61
 msgid "Directory"
 msgid "Directory"
 msgstr "Dossier"
 msgstr "Dossier"
 
 
-#: pg-view/ht/index.php:70
+#: pg-view/ht/index.php:71
 msgid "The one of your account"
 msgid "The one of your account"
 msgstr "Celle de votre compte"
 msgstr "Celle de votre compte"
 
 
-#: pg-view/ht/index.php:74
+#: pg-view/ht/index.php:75
 msgid "Authenticating the server"
 msgid "Authenticating the server"
 msgstr "Authentifier le serveur"
 msgstr "Authentifier le serveur"
 
 
-#: pg-view/ht/index.php:76
+#: pg-view/ht/index.php:77
 msgid "An SSHFP record is available."
 msgid "An SSHFP record is available."
 msgstr "Un enregistrement SSHFP est disponible."
 msgstr "Un enregistrement SSHFP est disponible."
 
 
-#: pg-view/ht/index.php:79
+#: pg-view/ht/index.php:80
 msgid "Plain public key"
 msgid "Plain public key"
 msgstr "Clé publique"
 msgstr "Clé publique"
 
 
-#: pg-view/ht/index.php:84
+#: pg-view/ht/index.php:85
 msgid "Public key fingerprint"
 msgid "Public key fingerprint"
 msgstr "Empreinte de la clé publique"
 msgstr "Empreinte de la clé publique"
 
 
-#: pg-view/ht/index.php:89
+#: pg-view/ht/index.php:90
 msgid "ASCII art"
 msgid "ASCII art"
 msgstr "Art ASCII"
 msgstr "Art ASCII"
 
 
-#: pg-view/ht/index.php:102
+#: pg-view/ht/index.php:103
 msgid "A content security policy (CSP) forbids Web browsers from loading JavaScript or third-party resources."
 msgid "A content security policy (CSP) forbids Web browsers from loading JavaScript or third-party resources."
 msgstr "Une politique de sécurité du contenu (CSP) interdit l'intégration de ressources tierces ou de JavaScript."
 msgstr "Une politique de sécurité du contenu (CSP) interdit l'intégration de ressources tierces ou de JavaScript."
 
 
-#: pg-view/ht/index.php:105
+#: pg-view/ht/index.php:106
 msgid "<code>.htaccess</code> configuration"
 msgid "<code>.htaccess</code> configuration"
 msgstr "Configuration par <code>.htaccess</code>"
 msgstr "Configuration par <code>.htaccess</code>"
 
 
-#: pg-view/ht/index.php:107
+#: pg-view/ht/index.php:108
 msgid "You can change the way the HTTP server answers to requests in a directory by setting some directives in a file named <code>.htaccess</code> at the root of this directory. Only the following directives are allowed:"
 msgid "You can change the way the HTTP server answers to requests in a directory by setting some directives in a file named <code>.htaccess</code> at the root of this directory. Only the following directives are allowed:"
 msgstr "Vous pouvez modifier la façon dont le serveur HTTP répond aux requêtes dans un dossier en indiquant des directives dans un fichier nommé <code>.htaccess</code> à la racine de ce dossier. Seules les directives suivantes sont autorisées&nbsp;:"
 msgstr "Vous pouvez modifier la façon dont le serveur HTTP répond aux requêtes dans un dossier en indiquant des directives dans un fichier nommé <code>.htaccess</code> à la racine de ce dossier. Seules les directives suivantes sont autorisées&nbsp;:"
 
 
-#: pg-view/ht/index.php:163
+#: pg-view/ht/index.php:164
 msgid "Accounts capabilities"
 msgid "Accounts capabilities"
 msgstr "Capacités des comptes"
 msgstr "Capacités des comptes"
 
 
-#: pg-view/ht/index.php:165
+#: pg-view/ht/index.php:166
 msgid "Testing"
 msgid "Testing"
 msgstr "De test"
 msgstr "De test"
 
 
-#: pg-view/ht/index.php:168 pg-view/ht/index.php:175
+#: pg-view/ht/index.php:169 pg-view/ht/index.php:176
 #, php-format
 #, php-format
 msgid "%s of SFTP quota"
 msgid "%s of SFTP quota"
 msgstr "Quota SFTP de %s"
 msgstr "Quota SFTP de %s"
 
 
-#: pg-view/ht/index.php:168 pg-view/ht/index.php:175
+#: pg-view/ht/index.php:169 pg-view/ht/index.php:176
 msgid "<abbr title=\"gibibyte\">GiB</abbr>"
 msgid "<abbr title=\"gibibyte\">GiB</abbr>"
 msgstr "<abbr title=\"gibioctet\">Gio</abbr>"
 msgstr "<abbr title=\"gibioctet\">Gio</abbr>"
 
 
-#: pg-view/ht/index.php:168 pg-view/ht/index.php:175
+#: pg-view/ht/index.php:169 pg-view/ht/index.php:176
 msgid "<abbr title=\"mebibyte\">MiB</abbr>"
 msgid "<abbr title=\"mebibyte\">MiB</abbr>"
 msgstr "<abbr title=\"mébioctet\">Mio</abbr>"
 msgstr "<abbr title=\"mébioctet\">Mio</abbr>"
 
 
-#: pg-view/ht/index.php:169
+#: pg-view/ht/index.php:170
 msgid "Let's Encrypt certificate from the staging environment (not trusted by clients)"
 msgid "Let's Encrypt certificate from the staging environment (not trusted by clients)"
 msgstr "Certificat Let's Encrypt de test (n'est pas reconnu par les clients)"
 msgstr "Certificat Let's Encrypt de test (n'est pas reconnu par les clients)"
 
 
-#: pg-view/ht/index.php:172
+#: pg-view/ht/index.php:173
 msgid "Approved"
 msgid "Approved"
 msgstr "Approuvé"
 msgstr "Approuvé"
 
 
-#: pg-view/ht/index.php:176
+#: pg-view/ht/index.php:177
 msgid "Stable Let's Encrypt certificates"
 msgid "Stable Let's Encrypt certificates"
 msgstr "Vrai certificat Let's Encrypt"
 msgstr "Vrai certificat Let's Encrypt"
 
 
-#: pg-view/ht/keys.php:2
+#: pg-view/ht/keys.php:3
 msgid "In addition to your password, you can also access your SFTP space using Ed25519 SSH keys. A key can be granted modification rights to the full space (<code>/</code>) or to any arbitrary subdirectory. A key is always  allowed to list any directory content."
 msgid "In addition to your password, you can also access your SFTP space using Ed25519 SSH keys. A key can be granted modification rights to the full space (<code>/</code>) or to any arbitrary subdirectory. A key is always  allowed to list any directory content."
 msgstr "En plus de la clé de passe, c'est également possible d'accéder à l'espace SFTP en utilisant des clés SSH Ed25519. Une clé peut être autorisée à modifier dans tout l'espace (<code>/</code>) ou dans un quelconque sous-dossier spécifique. Une clé est toujours autorisée à lister le contenu de n'importe quel dossier."
 msgstr "En plus de la clé de passe, c'est également possible d'accéder à l'espace SFTP en utilisant des clés SSH Ed25519. Une clé peut être autorisée à modifier dans tout l'espace (<code>/</code>) ou dans un quelconque sous-dossier spécifique. Une clé est toujours autorisée à lister le contenu de n'importe quel dossier."
 
 
-#: pg-view/ht/keys.php:17
+#: pg-view/ht/keys.php:18
 msgid "Add new SSH key access"
 msgid "Add new SSH key access"
 msgstr "Ajouter un nouvel accès par clé SSH"
 msgstr "Ajouter un nouvel accès par clé SSH"
 
 
-#: pg-view/ht/keys.php:17
+#: pg-view/ht/keys.php:18
 msgid "SSH key access"
 msgid "SSH key access"
 msgstr "Accès par clé SSH"
 msgstr "Accès par clé SSH"
 
 
-#: pg-view/ht/keys.php:19
+#: pg-view/ht/keys.php:20
 msgid "Public key"
 msgid "Public key"
 msgstr "Clé publique"
 msgstr "Clé publique"
 
 
-#: pg-view/ht/keys.php:23
+#: pg-view/ht/keys.php:24
 msgid "Allowed directory"
 msgid "Allowed directory"
 msgstr "Dossier autorisé"
 msgstr "Dossier autorisé"
 
 
-#: pg-view/ht/keys.php:30 pg-view/ns/sync.php:37
+#: pg-view/ht/keys.php:31 pg-view/ns/sync.php:38
 msgid "Update"
 msgid "Update"
 msgstr "Mettre à jour"
 msgstr "Mettre à jour"
 
 
-#: pg-view/ns/caa.php:3
+#: pg-view/ns/caa.php:4
 msgid "Flag"
 msgid "Flag"
 msgstr "Flag"
 msgstr "Flag"
 
 
-#: pg-view/ns/caa.php:7 pg-view/ns/print.php:56
+#: pg-view/ns/caa.php:8 pg-view/ns/print.php:57
 msgid "Tag"
 msgid "Tag"
 msgstr "Tag"
 msgstr "Tag"
 
 
-#: pg-view/ns/caa.php:11 pg-view/ns/form.ns.php:31 pg-view/ns/print.php:35
-#: pg-view/ns/tlsa.php:37 pg-view/reg/print.php:19
+#: pg-view/ns/caa.php:12 pg-view/ns/form.ns.php:33 pg-view/ns/print.php:36
+#: pg-view/ns/tlsa.php:38 pg-view/reg/print.php:13
 msgid "Value"
 msgid "Value"
 msgstr "Valeur"
 msgstr "Valeur"
 
 
-#: pg-view/ns/caa.php:15 pg-view/ns/cname.php:7 pg-view/ns/dname.php:7
-#: pg-view/ns/ip.php:5 pg-view/ns/loc.php:75 pg-view/ns/mx.php:11
-#: pg-view/ns/ns.php:7 pg-view/ns/srv.php:27 pg-view/ns/sshfp.php:29
-#: pg-view/ns/tlsa.php:43 pg-view/ns/txt.php:7 pg-view/reg/ds.php:56
-#: pg-view/reg/glue.php:29 pg-view/reg/ns.php:22
+#: pg-view/ns/caa.php:16 pg-view/ns/cname.php:8 pg-view/ns/dname.php:8
+#: pg-view/ns/ip.php:6 pg-view/ns/loc.php:76 pg-view/ns/mx.php:12
+#: pg-view/ns/ns.php:8 pg-view/ns/srv.php:28 pg-view/ns/sshfp.php:30
+#: pg-view/ns/tlsa.php:44 pg-view/ns/txt.php:8 pg-view/reg/ds.php:45
+#: pg-view/reg/glue.php:18 pg-view/reg/ns.php:11
 msgid "Apply"
 msgid "Apply"
 msgstr "Appliquer"
 msgstr "Appliquer"
 
 
-#: pg-view/ns/cname.php:3
+#: pg-view/ns/cname.php:4
 msgid "Canonical name"
 msgid "Canonical name"
 msgstr "Nom canonique"
 msgstr "Nom canonique"
 
 
-#: pg-view/ns/dname.php:3
+#: pg-view/ns/dname.php:4
 msgid "Delegation name"
 msgid "Delegation name"
 msgstr "Nom délégué"
 msgstr "Nom délégué"
 
 
-#: pg-view/ns/edit.php:2
+#: pg-view/ns/edit.php:3
 msgid "Zone to be changed"
 msgid "Zone to be changed"
 msgstr "Zone à modifier"
 msgstr "Zone à modifier"
 
 
-#: pg-view/ns/edit.php:12 pg-view/ns/print.php:20 pg-view/reg/print.php:11
+#: pg-view/ns/edit.php:13 pg-view/ns/print.php:21 pg-view/reg/edit.php:13
+#: pg-view/reg/print.php:5
 msgid "Display"
 msgid "Display"
 msgstr "Afficher"
 msgstr "Afficher"
 
 
-#: pg-view/ns/edit.php:23
+#: pg-view/ns/edit.php:24
 #, php-format
 #, php-format
-msgid "New content of the %s zone"
-msgstr "Nouveau contenu de la zone %s"
+msgid "Authoritative records for %s"
+msgstr "Enregistrements ayant autorité pour %s"
 
 
-#: pg-view/ns/edit.php:27
+#: pg-view/ns/edit.php:28 pg-view/reg/edit.php:28
 msgid "Replace"
 msgid "Replace"
 msgstr "Remplacer"
 msgstr "Remplacer"
 
 
-#: pg-view/ns/edit.php:38
+#: pg-view/ns/edit.php:39
 msgid "Default values"
 msgid "Default values"
 msgstr "Valeurs par défaut"
 msgstr "Valeurs par défaut"
 
 
-#: pg-view/ns/edit.php:40
+#: pg-view/ns/edit.php:41
 #, php-format
 #, php-format
 msgid "If the TTL is omitted, it will default to %s seconds."
 msgid "If the TTL is omitted, it will default to %s seconds."
 msgstr "Si le TTL est omis, il sera définit à %s secondes."
 msgstr "Si le TTL est omis, il sera définit à %s secondes."
 
 
-#: pg-view/ns/edit.php:42
+#: pg-view/ns/edit.php:43 pg-view/reg/edit.php:41
 msgid "Precising the class (<code>IN</code>) is optional."
 msgid "Precising the class (<code>IN</code>) is optional."
 msgstr "La précision de la classe (<code>IN</code>) est facultative."
 msgstr "La précision de la classe (<code>IN</code>) est facultative."
 
 
-#: pg-view/ns/edit.php:44
+#: pg-view/ns/edit.php:45
 msgid "Allowed values"
 msgid "Allowed values"
 msgstr "Valeurs autorisées"
 msgstr "Valeurs autorisées"
 
 
-#: pg-view/ns/edit.php:46
+#: pg-view/ns/edit.php:47 pg-view/reg/edit.php:43
 #, php-format
 #, php-format
-msgid "Submitted zone content is limited to %s characters."
-msgstr "La zone n'est pas autorisée à dépasser %s caractères."
+msgid "Submitted field content is limited to %s characters."
+msgstr "Le champ envoyé n'est pas autorisé à dépasser %s caractères."
 
 
-#: pg-view/ns/edit.php:48
+#: pg-view/ns/edit.php:49
 #, php-format
 #, php-format
 msgid "TTLs must last between %1$s and %2$s seconds."
 msgid "TTLs must last between %1$s and %2$s seconds."
 msgstr "Les TTLs ne sont autorisés qu'entre %1$s et %2$s secondes."
 msgstr "Les TTLs ne sont autorisés qu'entre %1$s et %2$s secondes."
 
 
-#: pg-view/ns/edit.php:50
-msgid "The only types that can be defined are:"
-msgstr "Les seuls types dont l'édition est autorisée sont&nbsp;:"
+#: pg-view/ns/edit.php:51 pg-view/reg/edit.php:47
+msgid "The only types that can be defined here are:"
+msgstr "Les seuls types qui peuvent être définis ici sont&nbsp;:"
 
 
-#: pg-view/ns/form.ns.php:1 pg-view/reg/ds.php:2 pg-view/reg/glue.php:2
-#: pg-view/reg/ns.php:2
+#: pg-view/ns/form.ns.php:2 pg-view/reg/select-action.inc.php:2
 msgid "Action"
 msgid "Action"
 msgstr "Action"
 msgstr "Action"
 
 
-#: pg-view/ns/form.ns.php:3 pg-view/ns/zone-add.php:8 pg-view/reg/ds.php:4
-#: pg-view/reg/glue.php:4 pg-view/reg/ns.php:4
+#: pg-view/ns/form.ns.php:4 pg-view/ns/zone-add.php:9
+#: pg-view/reg/select-action.inc.php:4
 msgid "Add"
 msgid "Add"
 msgstr "Ajouter"
 msgstr "Ajouter"
 
 
-#: pg-view/ns/form.ns.php:15 pg-view/ns/print.php:52 pg-view/ns/zone-del.php:2
+#: pg-view/ns/form.ns.php:16 pg-view/ns/print.php:53 pg-view/ns/zone-del.php:3
 msgid "Zone"
 msgid "Zone"
 msgstr "Zone"
 msgstr "Zone"
 
 
-#: pg-view/ns/form.ns.php:29 pg-view/ns/print.php:33 pg-view/reg/print.php:17
+#: pg-view/ns/form.ns.php:31 pg-view/ns/print.php:34 pg-view/reg/print.php:11
 msgid "TTL"
 msgid "TTL"
 msgstr "TTL"
 msgstr "TTL"
 
 
-#: pg-view/ns/form.ns.php:45
+#: pg-view/ns/form.ns.php:47
 msgid "Unit"
 msgid "Unit"
 msgstr "Unité"
 msgstr "Unité"
 
 
-#: pg-view/ns/form.ns.php:48
+#: pg-view/ns/form.ns.php:50
 msgid "second"
 msgid "second"
 msgstr "seconde"
 msgstr "seconde"
 
 
-#: pg-view/ns/form.ns.php:49
+#: pg-view/ns/form.ns.php:51
 msgid "minute"
 msgid "minute"
 msgstr "minute"
 msgstr "minute"
 
 
-#: pg-view/ns/form.ns.php:50
+#: pg-view/ns/form.ns.php:52
 msgid "hour"
 msgid "hour"
 msgstr "heure"
 msgstr "heure"
 
 
-#: pg-view/ns/form.ns.php:51
+#: pg-view/ns/form.ns.php:53
 msgid "day"
 msgid "day"
 msgstr "jour"
 msgstr "jour"
 
 
-#: pg-view/ns/index.php:2
+#: pg-view/ns/index.php:3
 msgid "This service allows to host and manage DNS records inside a DNS zone."
 msgid "This service allows to host and manage DNS records inside a DNS zone."
 msgstr "Ce service permet d'héberger et de gérer les enregistrements DNS à l'intérieur d'une zone DNS."
 msgstr "Ce service permet d'héberger et de gérer les enregistrements DNS à l'intérieur d'une zone DNS."
 
 
-#: pg-view/ns/index.php:8
+#: pg-view/ns/index.php:9
 msgid "Currently hosted zones"
 msgid "Currently hosted zones"
 msgstr "Zones actuellement hébergées"
 msgstr "Zones actuellement hébergées"
 
 
-#: pg-view/ns/index.php:26
+#: pg-view/ns/index.php:27
 msgid "A zone hosted on this service is served by these name servers:"
 msgid "A zone hosted on this service is served by these name servers:"
 msgstr "Une zone hébergée sur ce service est servie par les serveurs suivants&nbsp;:"
 msgstr "Une zone hébergée sur ce service est servie par les serveurs suivants&nbsp;:"
 
 
-#: pg-view/ns/ip.php:3 pg-view/reg/glue.php:26
+#: pg-view/ns/ip.php:4 pg-view/reg/glue.php:15
 msgid "IP address"
 msgid "IP address"
 msgstr "Adresse IP"
 msgstr "Adresse IP"
 
 
-#: pg-view/ns/loc.php:4
+#: pg-view/ns/loc.php:5
 msgid "Latitude"
 msgid "Latitude"
 msgstr "Latitude"
 msgstr "Latitude"
 
 
-#: pg-view/ns/loc.php:6 pg-view/ns/loc.php:34
+#: pg-view/ns/loc.php:7 pg-view/ns/loc.php:35
 msgid "Degrees"
 msgid "Degrees"
 msgstr "Dégrés"
 msgstr "Dégrés"
 
 
-#: pg-view/ns/loc.php:11 pg-view/ns/loc.php:39
+#: pg-view/ns/loc.php:12 pg-view/ns/loc.php:40
 msgid "Minutes"
 msgid "Minutes"
 msgstr "Minutes"
 msgstr "Minutes"
 
 
-#: pg-view/ns/loc.php:16 pg-view/ns/loc.php:44
+#: pg-view/ns/loc.php:17 pg-view/ns/loc.php:45
 msgid "Seconds"
 msgid "Seconds"
 msgstr "Secondes"
 msgstr "Secondes"
 
 
-#: pg-view/ns/loc.php:21 pg-view/ns/loc.php:49
+#: pg-view/ns/loc.php:22 pg-view/ns/loc.php:50
 msgid "Direction"
 msgid "Direction"
 msgstr "Direction"
 msgstr "Direction"
 
 
-#: pg-view/ns/loc.php:25
+#: pg-view/ns/loc.php:26
 msgid "North"
 msgid "North"
 msgstr "Nord"
 msgstr "Nord"
 
 
-#: pg-view/ns/loc.php:26
+#: pg-view/ns/loc.php:27
 msgid "South"
 msgid "South"
 msgstr "Sud"
 msgstr "Sud"
 
 
-#: pg-view/ns/loc.php:32
+#: pg-view/ns/loc.php:33
 msgid "Longitude"
 msgid "Longitude"
 msgstr "Longitude"
 msgstr "Longitude"
 
 
-#: pg-view/ns/loc.php:53
+#: pg-view/ns/loc.php:54
 msgid "East"
 msgid "East"
 msgstr "Est"
 msgstr "Est"
 
 
-#: pg-view/ns/loc.php:54
+#: pg-view/ns/loc.php:55
 msgid "West"
 msgid "West"
 msgstr "Ouest"
 msgstr "Ouest"
 
 
-#: pg-view/ns/loc.php:59
+#: pg-view/ns/loc.php:60
 msgid "Altitude"
 msgid "Altitude"
 msgstr "Altitude"
 msgstr "Altitude"
 
 
-#: pg-view/ns/loc.php:63
+#: pg-view/ns/loc.php:64
 msgid "Size"
 msgid "Size"
 msgstr "Taille"
 msgstr "Taille"
 
 
-#: pg-view/ns/loc.php:67
+#: pg-view/ns/loc.php:68
 msgid "Horizontal precision"
 msgid "Horizontal precision"
 msgstr "Précision horizontale"
 msgstr "Précision horizontale"
 
 
-#: pg-view/ns/loc.php:71
+#: pg-view/ns/loc.php:72
 msgid "Vertical precision"
 msgid "Vertical precision"
 msgstr "Précision verticale"
 msgstr "Précision verticale"
 
 
-#: pg-view/ns/mx.php:3 pg-view/ns/srv.php:4
+#: pg-view/ns/mx.php:4 pg-view/ns/srv.php:5
 msgid "Priority"
 msgid "Priority"
 msgstr "Priorité"
 msgstr "Priorité"
 
 
-#: pg-view/ns/mx.php:7
+#: pg-view/ns/mx.php:8
 msgid "Host"
 msgid "Host"
 msgstr "Hôte"
 msgstr "Hôte"
 
 
-#: pg-view/ns/ns.php:3 pg-view/reg/ns.php:18
+#: pg-view/ns/ns.php:4 pg-view/reg/ns.php:7
 msgid "Name server"
 msgid "Name server"
 msgstr "Serveur de nom"
 msgstr "Serveur de nom"
 
 
-#: pg-view/ns/print.php:3
+#: pg-view/ns/print.php:4
 msgid "Records table"
 msgid "Records table"
 msgstr "Tableau des enregistrements"
 msgstr "Tableau des enregistrements"
 
 
-#: pg-view/ns/print.php:6
+#: pg-view/ns/print.php:7
 msgid "DS record"
 msgid "DS record"
 msgstr "Enregistrement DS"
 msgstr "Enregistrement DS"
 
 
-#: pg-view/ns/print.php:9
+#: pg-view/ns/print.php:10
 msgid "Raw zonefile"
 msgid "Raw zonefile"
 msgstr "Fichier de zone brut"
 msgstr "Fichier de zone brut"
 
 
-#: pg-view/ns/print.php:11
+#: pg-view/ns/print.php:12
 msgid "Selected zone"
 msgid "Selected zone"
 msgstr "Zone"
 msgstr "Zone"
 
 
-#: pg-view/ns/print.php:34 pg-view/reg/print.php:18
+#: pg-view/ns/print.php:35 pg-view/reg/print.php:12
 msgid "Type"
 msgid "Type"
 msgstr "Type"
 msgstr "Type"
 
 
-#: pg-view/ns/print.php:60 pg-view/ns/sshfp.php:4 pg-view/reg/ds.php:22
+#: pg-view/ns/print.php:61 pg-view/ns/sshfp.php:5 pg-view/reg/ds.php:11
 msgid "Algorithm"
 msgid "Algorithm"
 msgstr "Algorithme"
 msgstr "Algorithme"
 
 
-#: pg-view/ns/print.php:64 pg-view/reg/ds.php:41
+#: pg-view/ns/print.php:65 pg-view/reg/ds.php:30
 msgid "Digest type"
 msgid "Digest type"
 msgstr "Type de condensat"
 msgstr "Type de condensat"
 
 
-#: pg-view/ns/print.php:68
+#: pg-view/ns/print.php:69
 msgid "Digest"
 msgid "Digest"
 msgstr "Condensat"
 msgstr "Condensat"
 
 
-#: pg-view/ns/srv.php:10
+#: pg-view/ns/srv.php:11
 msgid "Weight"
 msgid "Weight"
 msgstr "Poids"
 msgstr "Poids"
 
 
-#: pg-view/ns/srv.php:22
+#: pg-view/ns/srv.php:23
 msgid "Target"
 msgid "Target"
 msgstr "Cible"
 msgstr "Cible"
 
 
-#: pg-view/ns/sshfp.php:15
+#: pg-view/ns/sshfp.php:16
 msgid "Hash type"
 msgid "Hash type"
 msgstr "Type de hash"
 msgstr "Type de hash"
 
 
-#: pg-view/ns/sshfp.php:24
+#: pg-view/ns/sshfp.php:25
 msgid "Fingerprint"
 msgid "Fingerprint"
 msgstr "Empreinte"
 msgstr "Empreinte"
 
 
-#: pg-view/ns/sync.php:2
+#: pg-view/ns/sync.php:3
 #, php-format
 #, php-format
 msgid "AAAA, A and CAA records are regularly copied from the source domain to the target domain. Their TTLs are set to %s seconds."
 msgid "AAAA, A and CAA records are regularly copied from the source domain to the target domain. Their TTLs are set to %s seconds."
 msgstr "Les enregistrements AAAA, A et CAA sont régulièrement copiés du domain source vers le domain cible. Leurs TTLs sont définis à %s secondes."
 msgstr "Les enregistrements AAAA, A et CAA sont régulièrement copiés du domain source vers le domain cible. Leurs TTLs sont définis à %s secondes."
 
 
-#: pg-view/ns/sync.php:5
+#: pg-view/ns/sync.php:6
 msgid "Source domains that are not signed with DNSSEC are not synchronized. Synchronizations that remain broken may be deleted."
 msgid "Source domains that are not signed with DNSSEC are not synchronized. Synchronizations that remain broken may be deleted."
 msgstr "Les domains sources qui ne sont pas signés avec DNSSEC ne sont pas synchronisés. Les synchronisations qui restent cassées peuvent être supprimées."
 msgstr "Les domains sources qui ne sont pas signés avec DNSSEC ne sont pas synchronisés. Les synchronisations qui restent cassées peuvent être supprimées."
 
 
-#: pg-view/ns/sync.php:8
+#: pg-view/ns/sync.php:9
 msgid "This is meant to be used for apex domains, where CNAME records are not allowed. For non-apex domains, CNAME records should be used instead."
 msgid "This is meant to be used for apex domains, where CNAME records are not allowed. For non-apex domains, CNAME records should be used instead."
 msgstr "Ceci est destiné à être utilisé sur des domaines apex, où les enregistrements CNAME ne sont pas autorisés. Pour des domaines non-apex, les enregistrements CNAME devraient être utilisés à la place."
 msgstr "Ceci est destiné à être utilisé sur des domaines apex, où les enregistrements CNAME ne sont pas autorisés. Pour des domaines non-apex, les enregistrements CNAME devraient être utilisés à la place."
 
 
-#: pg-view/ns/sync.php:16
+#: pg-view/ns/sync.php:17
 msgid "Add new domain records to be synchronized"
 msgid "Add new domain records to be synchronized"
 msgstr "Ajouter de nouveaux enregistrements de domain à synchroniser"
 msgstr "Ajouter de nouveaux enregistrements de domain à synchroniser"
 
 
-#: pg-view/ns/sync.php:16
+#: pg-view/ns/sync.php:17
 msgid "Synchronized domain"
 msgid "Synchronized domain"
 msgstr "Domaine synchronisé"
 msgstr "Domaine synchronisé"
 
 
-#: pg-view/ns/sync.php:18
+#: pg-view/ns/sync.php:19
 msgid "Source domain"
 msgid "Source domain"
 msgstr "Domaine source"
 msgstr "Domaine source"
 
 
-#: pg-view/ns/sync.php:22
+#: pg-view/ns/sync.php:23
 msgid "Target domain"
 msgid "Target domain"
 msgstr "Domaine cible"
 msgstr "Domaine cible"
 
 
-#: pg-view/ns/tlsa.php:4
+#: pg-view/ns/tlsa.php:5
 msgid "Use"
 msgid "Use"
 msgstr "Utilisation"
 msgstr "Utilisation"
 
 
-#: pg-view/ns/tlsa.php:16
+#: pg-view/ns/tlsa.php:17
 msgid "Selector"
 msgid "Selector"
 msgstr "Selecteur"
 msgstr "Selecteur"
 
 
-#: pg-view/ns/tlsa.php:20
+#: pg-view/ns/tlsa.php:21
 msgid "the full certificate must match"
 msgid "the full certificate must match"
 msgstr "le certificat entier doit correspondre"
 msgstr "le certificat entier doit correspondre"
 
 
-#: pg-view/ns/tlsa.php:21
+#: pg-view/ns/tlsa.php:22
 msgid "the certificate public key must match"
 msgid "the certificate public key must match"
 msgstr "la clé publique du certificat doit correspondre"
 msgstr "la clé publique du certificat doit correspondre"
 
 
-#: pg-view/ns/tlsa.php:26
+#: pg-view/ns/tlsa.php:27
 msgid "Match type"
 msgid "Match type"
 msgstr "Type de correspondance"
 msgstr "Type de correspondance"
 
 
-#: pg-view/ns/tlsa.php:30
+#: pg-view/ns/tlsa.php:31
 msgid "full certificate"
 msgid "full certificate"
 msgstr "certificat entier"
 msgstr "certificat entier"
 
 
-#: pg-view/ns/txt.php:3
+#: pg-view/ns/txt.php:4
 msgid "Text"
 msgid "Text"
 msgstr "Texte"
 msgstr "Texte"
 
 
-#: pg-view/ns/txt.php:5
+#: pg-view/ns/txt.php:6
 msgid "Some text…"
 msgid "Some text…"
 msgstr "Du texte…"
 msgstr "Du texte…"
 
 
-#: pg-view/ns/zone-add.php:2
+#: pg-view/ns/zone-add.php:3
 #, php-format
 #, php-format
 msgid "To prove that you own this domain, it must have a NS record equal to %s when the form is being processed."
 msgid "To prove that you own this domain, it must have a NS record equal to %s when the form is being processed."
 msgstr "Pour prouver que vous possédez bien ce domaine, il doit posséder un enregistrement NS égal à %s lors du traitement de ce formulaire."
 msgstr "Pour prouver que vous possédez bien ce domaine, il doit posséder un enregistrement NS égal à %s lors du traitement de ce formulaire."
 
 
-#: pg-view/ns/zone-del.php:11
+#: pg-view/ns/zone-del.php:12
 msgid "Delete everything related to this zone"
 msgid "Delete everything related to this zone"
 msgstr "Supprimer tout de cette zone"
 msgstr "Supprimer tout de cette zone"
 
 
-#: pg-view/reg/ds.php:18
+#: pg-view/reg/ds.php:7
 msgid "Key tag"
 msgid "Key tag"
 msgstr "Tag de la clé"
 msgstr "Tag de la clé"
 
 
-#: pg-view/reg/ds.php:52
+#: pg-view/reg/ds.php:41
 msgid "Key"
 msgid "Key"
 msgstr "Condensat"
 msgstr "Condensat"
 
 
-#: pg-view/reg/glue.php:27
+#: pg-view/reg/edit.php:3
+msgid "Domain to be changed"
+msgstr "Domaine à modifier"
+
+#: pg-view/reg/edit.php:24
+#, php-format
+msgid "Delegation records for %s"
+msgstr "Enregistrements de délégation pour %s"
+
+#: pg-view/reg/edit.php:39
+msgid "Input values"
+msgstr "Saisie des valeurs"
+
+#: pg-view/reg/edit.php:45
+#, php-format
+msgid "TTL values are ignored and always set to %s seconds."
+msgstr "Les valeurs de TTL sont ignorées et toujours définies à %s secondes."
+
+#: pg-view/reg/glue.php:16
 #, php-format
 #, php-format
 msgid "%1$s or %2$s"
 msgid "%1$s or %2$s"
 msgstr "%1$s ou %2$s"
 msgstr "%1$s ou %2$s"
 
 
-#: pg-view/reg/index.php:2
+#: pg-view/reg/index.php:3
 #, php-format
 #, php-format
 msgid "This domain name registry allows to register domains ending with <code>%1$s</code>, for instance <code><em>domain</em>%1$s</code>."
 msgid "This domain name registry allows to register domains ending with <code>%1$s</code>, for instance <code><em>domain</em>%1$s</code>."
 msgstr "Ce registre de noms de domaine permet d'enregistrer des domaines se terminant par <code>%1$s</code>, par exemple <code><em>domaine</em>%1$s</code>."
 msgstr "Ce registre de noms de domaine permet d'enregistrer des domaines se terminant par <code>%1$s</code>, par exemple <code><em>domaine</em>%1$s</code>."
 
 
-#: pg-view/reg/index.php:7
+#: pg-view/reg/index.php:8
 msgid "Currently registered domains"
 msgid "Currently registered domains"
 msgstr "Domaines actuellement enregistrés"
 msgstr "Domaines actuellement enregistrés"
 
 
-#: pg-view/reg/index.php:27
+#: pg-view/reg/index.php:28
 msgid "Both <span aria-hidden=\"true\">⏳ </span><em>testing</em> and <span aria-hidden=\"true\">👤 </span><em>approved</em> accounts can register a domain under these suffixes:"
 msgid "Both <span aria-hidden=\"true\">⏳ </span><em>testing</em> and <span aria-hidden=\"true\">👤 </span><em>approved</em> accounts can register a domain under these suffixes:"
 msgstr "Les comptes <span aria-hidden=\"true\">⏳ </span><em>de test</em> et <span aria-hidden=\"true\">👤 </span><em>approuvés</em> peuvent enregistrer un domaine sous ces suffixes&nbsp;:"
 msgstr "Les comptes <span aria-hidden=\"true\">⏳ </span><em>de test</em> et <span aria-hidden=\"true\">👤 </span><em>approuvés</em> peuvent enregistrer un domaine sous ces suffixes&nbsp;:"
 
 
-#: pg-view/reg/index.php:38
+#: pg-view/reg/index.php:41
 msgid "Only <span aria-hidden=\"true\">👤 </span><em>approved</em> accounts can register a domain under these suffixes:"
 msgid "Only <span aria-hidden=\"true\">👤 </span><em>approved</em> accounts can register a domain under these suffixes:"
 msgstr "Seuls les comptes <span aria-hidden=\"true\">👤 </span><em>approuvés</em> peuvent enregistrer un domaine sous ces suffixes&nbsp;:"
 msgstr "Seuls les comptes <span aria-hidden=\"true\">👤 </span><em>approuvés</em> peuvent enregistrer un domaine sous ces suffixes&nbsp;:"
 
 
-#: pg-view/reg/index.php:49
+#: pg-view/reg/index.php:54
 msgid "Nobody can register a domain under these suffixes:"
 msgid "Nobody can register a domain under these suffixes:"
 msgstr "Personne ne peut enregistrer un domain sous ces suffixes&nbsp;:"
 msgstr "Personne ne peut enregistrer un domain sous ces suffixes&nbsp;:"
 
 
-#: pg-view/reg/index.php:63
+#: pg-view/reg/index.php:70
 msgid "Automatic updates from child zone"
 msgid "Automatic updates from child zone"
 msgstr "Mises à jour automatiques depuis la zone enfant"
 msgstr "Mises à jour automatiques depuis la zone enfant"
 
 
-#: pg-view/reg/index.php:64
+#: pg-view/reg/index.php:71
 msgid "CSYNC records"
 msgid "CSYNC records"
 msgstr "Enregistrements CSYNC"
 msgstr "Enregistrements CSYNC"
 
 
-#: pg-view/reg/index.php:66
+#: pg-view/reg/index.php:73
 msgid "The registry can synchronize NS records from the child zone if a CSYNC record is present at the apex of the child zone, has flags <code>1</code> and type bit map <code>NS</code>, and can be DNSSEC-validated. Others values are not supported."
 msgid "The registry can synchronize NS records from the child zone if a CSYNC record is present at the apex of the child zone, has flags <code>1</code> and type bit map <code>NS</code>, and can be DNSSEC-validated. Others values are not supported."
 msgstr "Le registre peut synchroniser les enregistrements NS depuis la zone enfant si un enregistrement CSYNC est présent à l'apex de la zone enfant, a les drapeaux <code>1</code> et le type bit map <code>NS</code>, et peut être validé par DNSSEC. Les autres valeurs ne sont pas supportées."
 msgstr "Le registre peut synchroniser les enregistrements NS depuis la zone enfant si un enregistrement CSYNC est présent à l'apex de la zone enfant, a les drapeaux <code>1</code> et le type bit map <code>NS</code>, et peut être validé par DNSSEC. Les autres valeurs ne sont pas supportées."
 
 
-#: pg-view/reg/index.php:68
+#: pg-view/reg/index.php:75
 msgid "DNSSEC and DS records"
 msgid "DNSSEC and DS records"
 msgstr "DNSSEC et enregistrements DS"
 msgstr "DNSSEC et enregistrements DS"
 
 
-#: pg-view/reg/index.php:70
+#: pg-view/reg/index.php:77
 msgid "Once DNSSEC has been manually enabled through the current interface, the delegated zone can publish a CDS record in order to update the DS record in the registry. A single CDS record with value <code>0 0 0 0</code> tells the registry to disable DNSSEC. Using a CDS record to enable DNSSEC is not supported."
 msgid "Once DNSSEC has been manually enabled through the current interface, the delegated zone can publish a CDS record in order to update the DS record in the registry. A single CDS record with value <code>0 0 0 0</code> tells the registry to disable DNSSEC. Using a CDS record to enable DNSSEC is not supported."
 msgstr "Une fois que DNSSEC a été manuellement activé en utilisant l'interface actuelle, la zone déléguée peut publier un enregistrement CDS afin de mettre à jour l'enregistrement DS dans le registre. Un unique enregistrement CDS avec pour valeur <code>0 0 0 0</code> indique au registre de désactiver DNSSEC. Utiliser un enregistrement CDS pour activer DNSSEC n'est pas supporté."
 msgstr "Une fois que DNSSEC a été manuellement activé en utilisant l'interface actuelle, la zone déléguée peut publier un enregistrement CDS afin de mettre à jour l'enregistrement DS dans le registre. Un unique enregistrement CDS avec pour valeur <code>0 0 0 0</code> indique au registre de désactiver DNSSEC. Utiliser un enregistrement CDS pour activer DNSSEC n'est pas supporté."
 
 
-#: pg-view/reg/register.php:2
+#: pg-view/reg/register.php:3
 msgid "Register a new domain on your account."
 msgid "Register a new domain on your account."
 msgstr "Enregistrer un nouveau domaine sur son compte."
 msgstr "Enregistrer un nouveau domaine sur son compte."
 
 
-#: pg-view/reg/register.php:18 pg-view/reg/transfer.php:14
+#: pg-view/reg/register.php:19 pg-view/reg/transfer.php:15
 msgid "Suffix"
 msgid "Suffix"
 msgstr "Suffixe"
 msgstr "Suffixe"
 
 
-#: pg-view/reg/register.php:31
+#: pg-view/reg/register.php:32
 msgid "Check availability"
 msgid "Check availability"
 msgstr "Vérifier sa disponibilité"
 msgstr "Vérifier sa disponibilité"
 
 
-#: pg-view/reg/register.php:33
+#: pg-view/reg/register.php:34
 msgid "Register"
 msgid "Register"
 msgstr "Enregistrer"
 msgstr "Enregistrer"
 
 
-#: pg-view/reg/transfer.php:2
+#: pg-view/reg/transfer.php:3
 #, php-format
 #, php-format
 msgid "To prove that you are allowed to receive the domain by its current owner, the domain must have an NS record equal to %s when the form is being processed. The NS record will be automatically deleted once validated."
 msgid "To prove that you are allowed to receive the domain by its current owner, the domain must have an NS record equal to %s when the form is being processed. The NS record will be automatically deleted once validated."
 msgstr "Pour prouver que vous êtes autorisé à recevoir le domaine par san possessaire actuele, ledit domaine doit posséder un enregistrement NS égal à %s lors du traitement de ce formulaire. Cet enregistrement sera automatiquement retiré une fois validé."
 msgstr "Pour prouver que vous êtes autorisé à recevoir le domaine par san possessaire actuele, ledit domaine doit posséder un enregistrement NS égal à %s lors du traitement de ce formulaire. Cet enregistrement sera automatiquement retiré une fois validé."
 
 
-#: pg-view/reg/transfer.php:7
+#: pg-view/reg/transfer.php:8
 msgid "Domain that will be transferred to this account"
 msgid "Domain that will be transferred to this account"
 msgstr "Domaine à transférer vers ce compte"
 msgstr "Domaine à transférer vers ce compte"
 
 
-#: pg-view/reg/transfer.php:26
+#: pg-view/reg/transfer.php:27
 msgid "Receive the domain"
 msgid "Receive the domain"
 msgstr "Recevoir le domaine"
 msgstr "Recevoir le domaine"
 
 
-#: pg-view/reg/unregister.php:2
+#: pg-view/reg/unregister.php:3
 msgid "This will unregister the domain, making it registerable by anyone again (after a delay of 1 year plus half the registration period, with a maximum of 8 years)."
 msgid "This will unregister the domain, making it registerable by anyone again (after a delay of 1 year plus half the registration period, with a maximum of 8 years)."
 msgstr "Ceci désenregistrera le domaine, ce qui le re-disponibilisera à tout le monde (après un délai de 1 an + la moitié de la durée d'enregistrement, avec un maximum de 8 ans)."
 msgstr "Ceci désenregistrera le domaine, ce qui le re-disponibilisera à tout le monde (après un délai de 1 an + la moitié de la durée d'enregistrement, avec un maximum de 8 ans)."
 
 
-#: pg-view/reg/unregister.php:16
+#: pg-view/reg/unregister.php:17
 msgid "Unregister"
 msgid "Unregister"
 msgstr "Désenregistrer"
 msgstr "Désenregistrer"

+ 293 - 256
locales/messages.pot

@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-07-16 20:50+0200\n"
+"POT-Creation-Date: 2023-07-31 01:03+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -25,8 +25,8 @@ msgstr ""
 msgid "Manage account"
 msgid "Manage account"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:13 view.php:21 pg-view/auth/login.php:12
-#: pg-view/auth/register.php:1
+#: pages.php:13 view.php:22 pg-view/auth/login.php:13
+#: pg-view/auth/register.php:2
 msgid "Log in"
 msgid "Log in"
 msgstr ""
 msgstr ""
 
 
@@ -34,7 +34,7 @@ msgstr ""
 msgid "Start a new navigation session with an existing account"
 msgid "Start a new navigation session with an existing account"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:18 view.php:19
+#: pages.php:18 view.php:20
 msgid "Log out"
 msgid "Log out"
 msgstr ""
 msgstr ""
 
 
@@ -117,189 +117,197 @@ msgstr ""
 msgid "Print every record related to a domain and served by the registry"
 msgid "Print every record related to a domain and served by the registry"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:67 pages.php:72 pages.php:117 pages.php:122 pages.php:127
-#: pages.php:132 pages.php:137 pages.php:142 pages.php:147 pages.php:152
-#: pages.php:157 pages.php:162
+#: pages.php:67
+msgid "Edit records"
+msgstr ""
+
+#: pages.php:68
+msgid "Set registry records to delegate a domain to chosen name servers"
+msgstr ""
+
+#: pages.php:72 pages.php:77 pages.php:122 pages.php:127 pages.php:132
+#: pages.php:137 pages.php:142 pages.php:147 pages.php:152 pages.php:157
+#: pages.php:162 pages.php:167
 #, php-format
 #, php-format
 msgid "%s records"
 msgid "%s records"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:68
+#: pages.php:73
 #, php-format
 #, php-format
 msgid "Indicate the name servers of a %s subdomain"
 msgid "Indicate the name servers of a %s subdomain"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:73
+#: pages.php:78
 msgid "Delegate <abbr title=\"Domain Name System Security Extensions\">DNSSEC</abbr> trust"
 msgid "Delegate <abbr title=\"Domain Name System Security Extensions\">DNSSEC</abbr> trust"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:77
+#: pages.php:82
 msgid "Receive a domain transfer"
 msgid "Receive a domain transfer"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:78
+#: pages.php:83
 msgid "Transfer a domain owned by another account to the current account"
 msgid "Transfer a domain owned by another account to the current account"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:82
+#: pages.php:87
 msgid "Glue records"
 msgid "Glue records"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:83
+#: pages.php:88
 msgid "Advanced: store the IP address of a name server whose domain is inside the domain it serves"
 msgid "Advanced: store the IP address of a name server whose domain is inside the domain it serves"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:89 pg-view/ns/index.php:24
+#: pages.php:94 pg-view/ns/index.php:25
 msgid "Name servers"
 msgid "Name servers"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:90
+#: pages.php:95
 msgid "Host and manage domain's records"
 msgid "Host and manage domain's records"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:93
+#: pages.php:98
 msgid "Add zone"
 msgid "Add zone"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:94
+#: pages.php:99
 #, php-format
 #, php-format
 msgid "The zone will be managed by %s name servers"
 msgid "The zone will be managed by %s name servers"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:98
+#: pages.php:103
 msgid "Delete zone"
 msgid "Delete zone"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:99
+#: pages.php:104
 msgid "Erase all zone data"
 msgid "Erase all zone data"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:102
+#: pages.php:107
 msgid "Display zone"
 msgid "Display zone"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:103
+#: pages.php:108
 msgid "Print zonefile content"
 msgid "Print zonefile content"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:107
+#: pages.php:112
 msgid "Edit zone"
 msgid "Edit zone"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:108
+#: pages.php:113
 msgid "Change zonefile content"
 msgid "Change zonefile content"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:112
+#: pages.php:117
 msgid "AAAA and A records"
 msgid "AAAA and A records"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:113
+#: pages.php:118
 msgid "Store domain's IP address"
 msgid "Store domain's IP address"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:118
+#: pages.php:123
 msgid "Store zone's name server"
 msgid "Store zone's name server"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:123
+#: pages.php:128
 msgid "Associate text to domain"
 msgid "Associate text to domain"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:128
+#: pages.php:133
 msgid "Limit the certificate authorities allowed to certify the domain"
 msgid "Limit the certificate authorities allowed to certify the domain"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:133
+#: pages.php:138
 msgid "Store the location of a domain's service"
 msgid "Store the location of a domain's service"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:138
+#: pages.php:143
 msgid "Store the email server's address"
 msgid "Store the email server's address"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:143
+#: pages.php:148
 msgid "Store <abbr title=\"Secure SHell\">SSH</abbr> public keys fingerprints"
 msgid "Store <abbr title=\"Secure SHell\">SSH</abbr> public keys fingerprints"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:148
+#: pages.php:153
 msgid "Setup <abbr title=\"DNS-based Authentication of Named Entities\">DANE</abbr> by publishing the <abbr title=\"Transport Layer Security\">TLS</abbr> certificate fingerprint"
 msgid "Setup <abbr title=\"DNS-based Authentication of Named Entities\">DANE</abbr> by publishing the <abbr title=\"Transport Layer Security\">TLS</abbr> certificate fingerprint"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:153
+#: pages.php:158
 msgid "Define a domain as an alias of another"
 msgid "Define a domain as an alias of another"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:158
+#: pages.php:163
 msgid "Define all subdomains of a domain as aliases of subdomains of another domain"
 msgid "Define all subdomains of a domain as aliases of subdomains of another domain"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:163
+#: pages.php:168
 msgid "Store geographic coordinates"
 msgid "Store geographic coordinates"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:167
+#: pages.php:172
 #, php-format
 #, php-format
 msgid "Synchronized records"
 msgid "Synchronized records"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:168
+#: pages.php:173
 msgid "Regularly fetch distant records and update them to a local zone"
 msgid "Regularly fetch distant records and update them to a local zone"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:174
+#: pages.php:179
 msgid "Web"
 msgid "Web"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:175
+#: pages.php:180
 msgid "Upload a static website into an <abbr title=\"SSH File Transfer Protocol\">SFTP</abbr> space"
 msgid "Upload a static website into an <abbr title=\"SSH File Transfer Protocol\">SFTP</abbr> space"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:178
+#: pages.php:183
 #, php-format
 #, php-format
 msgid "%s subpath access"
 msgid "%s subpath access"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:179 pages.php:184 pages.php:189
+#: pages.php:184 pages.php:189 pages.php:194
 #, php-format
 #, php-format
 msgid "Its URL will look like %s"
 msgid "Its URL will look like %s"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:179 pages.php:184 pages.php:189
+#: pages.php:184 pages.php:189 pages.php:194
 msgid "mysite"
 msgid "mysite"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:183
+#: pages.php:188
 #, php-format
 #, php-format
 msgid "%s subdomain access"
 msgid "%s subdomain access"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:188
+#: pages.php:193
 msgid "Dedicated domain with Let's Encrypt certificate access"
 msgid "Dedicated domain with Let's Encrypt certificate access"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:193
+#: pages.php:198
 msgid "Onion service access"
 msgid "Onion service access"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:194
+#: pages.php:199
 #, php-format
 #, php-format
 msgid "Its URL will look like %s, and work only through the Tor network"
 msgid "Its URL will look like %s, and work only through the Tor network"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:198 pg-view/ht/del.php:18
+#: pages.php:203 pg-view/ht/del.php:19
 msgid "Delete access"
 msgid "Delete access"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:199
+#: pages.php:204
 msgid "Delete an existing HTTP access from a subdirectory of the SFTP space"
 msgid "Delete an existing HTTP access from a subdirectory of the SFTP space"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:202
+#: pages.php:207
 msgid "Manage SSH keys"
 msgid "Manage SSH keys"
 msgstr ""
 msgstr ""
 
 
-#: pages.php:203
+#: pages.php:208
 msgid "Choose what SSH key can edit what directory"
 msgid "Choose what SSH key can edit what directory"
 msgstr ""
 msgstr ""
 
 
@@ -307,7 +315,7 @@ msgstr ""
 msgid "This account doesn't exist anymore. Log out to end this ghost session."
 msgid "This account doesn't exist anymore. Log out to end this ghost session."
 msgstr ""
 msgstr ""
 
 
-#: router.php:106 view.php:39
+#: router.php:106 view.php:40
 msgid "This service is currently under maintenance. No action can be taken on it until an administrator finishes repairing it."
 msgid "This service is currently under maintenance. No action can be taken on it until an administrator finishes repairing it."
 msgstr ""
 msgstr ""
 
 
@@ -315,24 +323,24 @@ msgstr ""
 msgid "You need to be logged in to do this."
 msgid "You need to be logged in to do this."
 msgstr ""
 msgstr ""
 
 
-#: view.php:19
+#: view.php:20
 msgid "You are using a testing account. It may be deleted anytime."
 msgid "You are using a testing account. It may be deleted anytime."
 msgstr ""
 msgstr ""
 
 
-#: view.php:19
+#: view.php:20
 msgid "Read more"
 msgid "Read more"
 msgstr ""
 msgstr ""
 
 
-#: view.php:21
+#: view.php:22
 msgid "Anonymous"
 msgid "Anonymous"
 msgstr ""
 msgstr ""
 
 
-#: view.php:44
+#: view.php:45
 #, php-format
 #, php-format
 msgid "This form won't be accepted because you need to %slog in%s first."
 msgid "This form won't be accepted because you need to %slog in%s first."
 msgstr ""
 msgstr ""
 
 
-#: view.php:51
+#: view.php:52
 #, php-format
 #, php-format
 msgid "%sSource code%s available under %s."
 msgid "%sSource code%s available under %s."
 msgstr ""
 msgstr ""
@@ -366,7 +374,7 @@ msgstr ""
 msgid "Wrong proof."
 msgid "Wrong proof."
 msgstr ""
 msgstr ""
 
 
-#: fn/dns.php:77
+#: fn/dns.php:76
 msgid "IP address malformed."
 msgid "IP address malformed."
 msgstr ""
 msgstr ""
 
 
@@ -374,17 +382,25 @@ msgstr ""
 msgid "Domain malformed."
 msgid "Domain malformed."
 msgstr ""
 msgstr ""
 
 
-#: fn/ns.php:33 pg-act/ns/edit.php:25
+#: fn/ns.php:33 pg-act/ns/edit.php:27
 #, php-format
 #, php-format
 msgid "TTLs shorter than %s seconds are forbidden."
 msgid "TTLs shorter than %s seconds are forbidden."
 msgstr ""
 msgstr ""
 
 
-#: fn/ns.php:35 pg-act/ns/edit.php:27
+#: fn/ns.php:35 pg-act/ns/edit.php:29
 #, php-format
 #, php-format
 msgid "TTLs longer than %s seconds are forbidden."
 msgid "TTLs longer than %s seconds are forbidden."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/index.php:3
+#: fn/reg.php:73
+msgid "You can only set a NS/DS record for an apex domain."
+msgstr ""
+
+#: fn/reg.php:75
+msgid "You can't set a record for another domain."
+msgstr ""
+
+#: pg-view/index.php:4
 msgid "About this installation"
 msgid "About this installation"
 msgstr ""
 msgstr ""
 
 
@@ -417,7 +433,7 @@ msgstr ""
 msgid "Password updated."
 msgid "Password updated."
 msgstr ""
 msgstr ""
 
 
-#: pg-act/auth/register.php:4 pg-view/auth/register.php:3
+#: pg-act/auth/register.php:4 pg-view/auth/register.php:4
 msgid "Registrations are currently closed on this installation."
 msgid "Registrations are currently closed on this installation."
 msgstr ""
 msgstr ""
 
 
@@ -497,27 +513,27 @@ msgstr ""
 #: pg-act/ns/caa.php:25 pg-act/ns/cname.php:16 pg-act/ns/dname.php:16
 #: pg-act/ns/caa.php:25 pg-act/ns/cname.php:16 pg-act/ns/dname.php:16
 #: pg-act/ns/ip.php:16 pg-act/ns/loc.php:72 pg-act/ns/mx.php:20
 #: pg-act/ns/ip.php:16 pg-act/ns/loc.php:72 pg-act/ns/mx.php:20
 #: pg-act/ns/ns.php:16 pg-act/ns/srv.php:28 pg-act/ns/sshfp.php:25
 #: pg-act/ns/ns.php:16 pg-act/ns/srv.php:28 pg-act/ns/sshfp.php:25
-#: pg-act/ns/tlsa.php:29 pg-act/ns/txt.php:17 pg-act/reg/ds.php:30
-#: pg-act/reg/glue.php:14 pg-act/reg/ns.php:14
+#: pg-act/ns/tlsa.php:29 pg-act/ns/txt.php:17 pg-act/reg/ds.php:12
+#: pg-act/reg/glue.php:13 pg-act/reg/ns.php:12
 msgid "Modification done."
 msgid "Modification done."
 msgstr ""
 msgstr ""
 
 
-#: pg-act/ns/edit.php:17
+#: pg-act/ns/edit.php:19 pg-act/reg/edit.php:14
 #, php-format
 #, php-format
 msgid "The zone is limited to %s characters."
 msgid "The zone is limited to %s characters."
 msgstr ""
 msgstr ""
 
 
-#: pg-act/ns/edit.php:21
+#: pg-act/ns/edit.php:23 pg-act/reg/edit.php:18
 msgid "The following line does not match the expected format: "
 msgid "The following line does not match the expected format: "
 msgstr ""
 msgstr ""
 
 
-#: pg-act/ns/edit.php:23
+#: pg-act/ns/edit.php:25 pg-act/reg/edit.php:20 pg-act/reg/edit.php:28
 #, php-format
 #, php-format
 msgid "The %s type is not allowed."
 msgid "The %s type is not allowed."
 msgstr ""
 msgstr ""
 
 
-#: pg-act/ns/edit.php:38
-msgid "Sent zone content is not correct (according to <code>kzonecheck</code>)."
+#: pg-act/ns/edit.php:40 pg-act/reg/edit.php:51
+msgid "Sent content is not correct (according to <code>kzonecheck</code>)."
 msgstr ""
 msgstr ""
 
 
 #: pg-act/ns/sync.php:19
 #: pg-act/ns/sync.php:19
@@ -548,6 +564,10 @@ msgstr ""
 msgid "Zone deleted."
 msgid "Zone deleted."
 msgstr ""
 msgstr ""
 
 
+#: pg-act/reg/edit.php:22
+msgid "A DS record expects 4 arguments."
+msgstr ""
+
 #: pg-act/reg/register.php:4 pg-act/reg/transfer.php:4
 #: pg-act/reg/register.php:4 pg-act/reg/transfer.php:4
 msgid "This format of subdomain is not allowed."
 msgid "This format of subdomain is not allowed."
 msgstr ""
 msgstr ""
@@ -596,705 +616,722 @@ msgstr ""
 msgid "Domain unregistered."
 msgid "Domain unregistered."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/approval.php:2
+#: pg-view/auth/approval.php:3
 msgid "This form allows to use an approval key to validate your account. Approval keys are distributed by an administrator upon request."
 msgid "This form allows to use an approval key to validate your account. Approval keys are distributed by an administrator upon request."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/approval.php:6
+#: pg-view/auth/approval.php:7
 msgid "Approval key"
 msgid "Approval key"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/approval.php:9
+#: pg-view/auth/approval.php:10
 msgid "Use for this account"
 msgid "Use for this account"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:3
+#: pg-view/auth/index.php:4
 msgid "Account type"
 msgid "Account type"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:9
+#: pg-view/auth/index.php:10
 msgid "You are currently using a <strong>testing</strong> account."
 msgid "You are currently using a <strong>testing</strong> account."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:10
+#: pg-view/auth/index.php:11
 msgid "You are currently using an <strong>approved</strong> account."
 msgid "You are currently using an <strong>approved</strong> account."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:13
+#: pg-view/auth/index.php:14
 msgid "You are not logged in."
 msgid "You are not logged in."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:18
+#: pg-view/auth/index.php:19
 msgid "When an account is created, it's a <em>testing</em> account. A testing account is only temporary and with limited capabilities on the services. Once the account is validated by using an approval key requested to an administrator, it becomes an <em>approved</em> account."
 msgid "When an account is created, it's a <em>testing</em> account. A testing account is only temporary and with limited capabilities on the services. Once the account is validated by using an approval key requested to an administrator, it becomes an <em>approved</em> account."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:21
+#: pg-view/auth/index.php:22
 msgid "Rate limit"
 msgid "Rate limit"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:25
+#: pg-view/auth/index.php:26
 #, php-format
 #, php-format
 msgid "Your account is at %s%% of the rate limit."
 msgid "Your account is at %s%% of the rate limit."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:27
+#: pg-view/auth/index.php:28
 msgid "Most of the form submissions bring you closer to the rate limit. If you reach it, you need to wait in order to be able to submit forms again."
 msgid "Most of the form submissions bring you closer to the rate limit. If you reach it, you need to wait in order to be able to submit forms again."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:31
+#: pg-view/auth/index.php:32
 msgid "Internal ID"
 msgid "Internal ID"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/index.php:33
+#: pg-view/auth/index.php:34
 #, php-format
 #, php-format
 msgid "The current account's internal ID is %s."
 msgid "The current account's internal ID is %s."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/login.php:1
+#: pg-view/auth/login.php:2
 msgid "New?"
 msgid "New?"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/login.php:1 pg-view/auth/register.php:16
+#: pg-view/auth/login.php:2 pg-view/auth/register.php:17
 msgid "Create an account"
 msgid "Create an account"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/login.php:4 pg-view/auth/register.php:6 pg-view/ht/index.php:64
+#: pg-view/auth/login.php:5 pg-view/auth/register.php:7 pg-view/ht/index.php:65
 msgid "Username"
 msgid "Username"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/login.php:8 pg-view/auth/register.php:11
-#: pg-view/ht/index.php:68
+#: pg-view/auth/login.php:9 pg-view/auth/register.php:12
+#: pg-view/ht/index.php:69
 msgid "Password"
 msgid "Password"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/password.php:2 pg-view/auth/unregister.php:6
-#: pg-view/auth/username.php:2
+#: pg-view/auth/password.php:3 pg-view/auth/unregister.php:7
+#: pg-view/auth/username.php:3
 msgid "Current password"
 msgid "Current password"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/password.php:5
+#: pg-view/auth/password.php:6
 msgid "New password"
 msgid "New password"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/password.php:8
+#: pg-view/auth/password.php:9
 msgid "Update password"
 msgid "Update password"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/register.php:1
+#: pg-view/auth/register.php:2
 msgid "Already have an account?"
 msgid "Already have an account?"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/register.php:12
+#: pg-view/auth/register.php:13
 #, php-format
 #, php-format
 msgid "Minimum %1$s characters, or %2$s characters if it contains lowercase, uppercase and digit."
 msgid "Minimum %1$s characters, or %2$s characters if it contains lowercase, uppercase and digit."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/unregister.php:2
+#: pg-view/auth/unregister.php:3
 msgid "This will delete every resource managed by the current account, including registered domains, hosted DNS records, websites files and cryptographic keys for Onion services and DNSSEC."
 msgid "This will delete every resource managed by the current account, including registered domains, hosted DNS records, websites files and cryptographic keys for Onion services and DNSSEC."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/unregister.php:10
+#: pg-view/auth/unregister.php:11
 msgid "Delete the current account and everything related (required)"
 msgid "Delete the current account and everything related (required)"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/unregister.php:12 pg-view/ns/form.ns.php:4 pg-view/reg/ds.php:5
-#: pg-view/reg/glue.php:5 pg-view/reg/ns.php:5
+#: pg-view/auth/unregister.php:13 pg-view/ns/form.ns.php:5
+#: pg-view/reg/select-action.inc.php:5
 msgid "Delete"
 msgid "Delete"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/username.php:5
+#: pg-view/auth/username.php:6
 msgid "New username"
 msgid "New username"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/auth/username.php:8
+#: pg-view/auth/username.php:9
 msgid "Update username"
 msgid "Update username"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-dns.php:2
+#: pg-view/ht/add-dns.php:3
 msgid "A Let's Encrypt certificate will be obtained."
 msgid "A Let's Encrypt certificate will be obtained."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-dns.php:6
+#: pg-view/ht/add-dns.php:7
 msgid "The domain must have the following records when the form is being processed."
 msgid "The domain must have the following records when the form is being processed."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-dns.php:29 pg-view/ns/form.ns.php:8 pg-view/ns/print.php:32
-#: pg-view/ns/zone-add.php:6 pg-view/reg/ds.php:8 pg-view/reg/glue.php:8
-#: pg-view/reg/glue.php:15 pg-view/reg/ns.php:8 pg-view/reg/print.php:2
-#: pg-view/reg/print.php:16 pg-view/reg/register.php:11
-#: pg-view/reg/unregister.php:6
+#: pg-view/ht/add-dns.php:30 pg-view/ns/form.ns.php:9 pg-view/ns/print.php:33
+#: pg-view/ns/zone-add.php:7 pg-view/reg/glue.php:5 pg-view/reg/print.php:10
+#: pg-view/reg/register.php:12 pg-view/reg/select-domain.inc.php:2
+#: pg-view/reg/unregister.php:7
 msgid "Domain"
 msgid "Domain"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-dns.php:31 pg-view/ht/add-onion.php:2
-#: pg-view/ht/add-subdomain.php:8 pg-view/ht/add-subpath.php:8
+#: pg-view/ht/add-dns.php:32 pg-view/ht/add-onion.php:3
+#: pg-view/ht/add-subdomain.php:9 pg-view/ht/add-subpath.php:9
 msgid "Target directory"
 msgid "Target directory"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-dns.php:40 pg-view/ht/add-onion.php:11
-#: pg-view/ht/add-subdomain.php:17 pg-view/ht/add-subpath.php:17
+#: pg-view/ht/add-dns.php:41 pg-view/ht/add-onion.php:12
+#: pg-view/ht/add-subdomain.php:18 pg-view/ht/add-subpath.php:18
 msgid "Setup access"
 msgid "Setup access"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-subdomain.php:2 pg-view/reg/register.php:6
+#: pg-view/ht/add-subdomain.php:3 pg-view/reg/register.php:7
 #, php-format
 #, php-format
 msgid "The subdomain can only contain %1$s, %2$s and %3$s, and must be between 4 and 63 characters. It can't have an hyphen (%3$s) in first, last or both third and fourth position."
 msgid "The subdomain can only contain %1$s, %2$s and %3$s, and must be between 4 and 63 characters. It can't have an hyphen (%3$s) in first, last or both third and fourth position."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-subdomain.php:6 pg-view/ns/form.ns.php:10
-#: pg-view/reg/glue.php:10 pg-view/reg/register.php:13
-#: pg-view/reg/transfer.php:9
+#: pg-view/ht/add-subdomain.php:7 pg-view/ns/form.ns.php:11
+#: pg-view/reg/glue.php:7 pg-view/reg/register.php:14
+#: pg-view/reg/transfer.php:10
 msgid "Subdomain"
 msgid "Subdomain"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-subpath.php:2
+#: pg-view/ht/add-subpath.php:3
 #, php-format
 #, php-format
 msgid "The path can only contain %1$s, %2$s and %3$s, and must be between 4 and 63 characters."
 msgid "The path can only contain %1$s, %2$s and %3$s, and must be between 4 and 63 characters."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/add-subpath.php:6
+#: pg-view/ht/add-subpath.php:7
 msgid "Path"
 msgid "Path"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/del.php:2
+#: pg-view/ht/del.php:3
 msgid "Access to delete"
 msgid "Access to delete"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/del.php:13
+#: pg-view/ht/del.php:14
 #, php-format
 #, php-format
 msgid "%1$s to %2$s"
 msgid "%1$s to %2$s"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:2
+#: pg-view/ht/index.php:3
 msgid "This service allows you to send files on the server using SFTP, and to make them publicly available with HTTP."
 msgid "This service allows you to send files on the server using SFTP, and to make them publicly available with HTTP."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:8
+#: pg-view/ht/index.php:9
 msgid "Currently hosted sites"
 msgid "Currently hosted sites"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:38
+#: pg-view/ht/index.php:39
 msgid "Adding a site access"
 msgid "Adding a site access"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:40
+#: pg-view/ht/index.php:41
 #, php-format
 #, php-format
 msgid "In order to be able to set up an HTTP site with this service, a subdirectory for this site must be created inside the SFTP space first. The name of this subdirectory can only contain %1$s, %2$s, %3$s, %4$s and %5$s."
 msgid "In order to be able to set up an HTTP site with this service, a subdirectory for this site must be created inside the SFTP space first. The name of this subdirectory can only contain %1$s, %2$s, %3$s, %4$s and %5$s."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:44
+#: pg-view/ht/index.php:45
 msgid "Connecting to the SFTP server"
 msgid "Connecting to the SFTP server"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:52
+#: pg-view/ht/index.php:53
 msgid "Server"
 msgid "Server"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:56 pg-view/ns/srv.php:16
+#: pg-view/ht/index.php:57 pg-view/ns/srv.php:17
 msgid "Port"
 msgid "Port"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:60
+#: pg-view/ht/index.php:61
 msgid "Directory"
 msgid "Directory"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:70
+#: pg-view/ht/index.php:71
 msgid "The one of your account"
 msgid "The one of your account"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:74
+#: pg-view/ht/index.php:75
 msgid "Authenticating the server"
 msgid "Authenticating the server"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:76
+#: pg-view/ht/index.php:77
 msgid "An SSHFP record is available."
 msgid "An SSHFP record is available."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:79
+#: pg-view/ht/index.php:80
 msgid "Plain public key"
 msgid "Plain public key"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:84
+#: pg-view/ht/index.php:85
 msgid "Public key fingerprint"
 msgid "Public key fingerprint"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:89
+#: pg-view/ht/index.php:90
 msgid "ASCII art"
 msgid "ASCII art"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:102
+#: pg-view/ht/index.php:103
 msgid "A content security policy (CSP) forbids Web browsers from loading JavaScript or third-party resources."
 msgid "A content security policy (CSP) forbids Web browsers from loading JavaScript or third-party resources."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:105
+#: pg-view/ht/index.php:106
 msgid "<code>.htaccess</code> configuration"
 msgid "<code>.htaccess</code> configuration"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:107
+#: pg-view/ht/index.php:108
 msgid "You can change the way the HTTP server answers to requests in a directory by setting some directives in a file named <code>.htaccess</code> at the root of this directory. Only the following directives are allowed:"
 msgid "You can change the way the HTTP server answers to requests in a directory by setting some directives in a file named <code>.htaccess</code> at the root of this directory. Only the following directives are allowed:"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:163
+#: pg-view/ht/index.php:164
 msgid "Accounts capabilities"
 msgid "Accounts capabilities"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:165
+#: pg-view/ht/index.php:166
 msgid "Testing"
 msgid "Testing"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:168 pg-view/ht/index.php:175
+#: pg-view/ht/index.php:169 pg-view/ht/index.php:176
 #, php-format
 #, php-format
 msgid "%s of SFTP quota"
 msgid "%s of SFTP quota"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:168 pg-view/ht/index.php:175
+#: pg-view/ht/index.php:169 pg-view/ht/index.php:176
 msgid "<abbr title=\"gibibyte\">GiB</abbr>"
 msgid "<abbr title=\"gibibyte\">GiB</abbr>"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:168 pg-view/ht/index.php:175
+#: pg-view/ht/index.php:169 pg-view/ht/index.php:176
 msgid "<abbr title=\"mebibyte\">MiB</abbr>"
 msgid "<abbr title=\"mebibyte\">MiB</abbr>"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:169
+#: pg-view/ht/index.php:170
 msgid "Let's Encrypt certificate from the staging environment (not trusted by clients)"
 msgid "Let's Encrypt certificate from the staging environment (not trusted by clients)"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:172
+#: pg-view/ht/index.php:173
 msgid "Approved"
 msgid "Approved"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/index.php:176
+#: pg-view/ht/index.php:177
 msgid "Stable Let's Encrypt certificates"
 msgid "Stable Let's Encrypt certificates"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/keys.php:2
+#: pg-view/ht/keys.php:3
 msgid "In addition to your password, you can also access your SFTP space using Ed25519 SSH keys. A key can be granted modification rights to the full space (<code>/</code>) or to any arbitrary subdirectory. A key is always  allowed to list any directory content."
 msgid "In addition to your password, you can also access your SFTP space using Ed25519 SSH keys. A key can be granted modification rights to the full space (<code>/</code>) or to any arbitrary subdirectory. A key is always  allowed to list any directory content."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/keys.php:17
+#: pg-view/ht/keys.php:18
 msgid "Add new SSH key access"
 msgid "Add new SSH key access"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/keys.php:17
+#: pg-view/ht/keys.php:18
 msgid "SSH key access"
 msgid "SSH key access"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/keys.php:19
+#: pg-view/ht/keys.php:20
 msgid "Public key"
 msgid "Public key"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/keys.php:23
+#: pg-view/ht/keys.php:24
 msgid "Allowed directory"
 msgid "Allowed directory"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ht/keys.php:30 pg-view/ns/sync.php:37
+#: pg-view/ht/keys.php:31 pg-view/ns/sync.php:38
 msgid "Update"
 msgid "Update"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/caa.php:3
+#: pg-view/ns/caa.php:4
 msgid "Flag"
 msgid "Flag"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/caa.php:7 pg-view/ns/print.php:56
+#: pg-view/ns/caa.php:8 pg-view/ns/print.php:57
 msgid "Tag"
 msgid "Tag"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/caa.php:11 pg-view/ns/form.ns.php:31 pg-view/ns/print.php:35
-#: pg-view/ns/tlsa.php:37 pg-view/reg/print.php:19
+#: pg-view/ns/caa.php:12 pg-view/ns/form.ns.php:33 pg-view/ns/print.php:36
+#: pg-view/ns/tlsa.php:38 pg-view/reg/print.php:13
 msgid "Value"
 msgid "Value"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/caa.php:15 pg-view/ns/cname.php:7 pg-view/ns/dname.php:7
-#: pg-view/ns/ip.php:5 pg-view/ns/loc.php:75 pg-view/ns/mx.php:11
-#: pg-view/ns/ns.php:7 pg-view/ns/srv.php:27 pg-view/ns/sshfp.php:29
-#: pg-view/ns/tlsa.php:43 pg-view/ns/txt.php:7 pg-view/reg/ds.php:56
-#: pg-view/reg/glue.php:29 pg-view/reg/ns.php:22
+#: pg-view/ns/caa.php:16 pg-view/ns/cname.php:8 pg-view/ns/dname.php:8
+#: pg-view/ns/ip.php:6 pg-view/ns/loc.php:76 pg-view/ns/mx.php:12
+#: pg-view/ns/ns.php:8 pg-view/ns/srv.php:28 pg-view/ns/sshfp.php:30
+#: pg-view/ns/tlsa.php:44 pg-view/ns/txt.php:8 pg-view/reg/ds.php:45
+#: pg-view/reg/glue.php:18 pg-view/reg/ns.php:11
 msgid "Apply"
 msgid "Apply"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/cname.php:3
+#: pg-view/ns/cname.php:4
 msgid "Canonical name"
 msgid "Canonical name"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/dname.php:3
+#: pg-view/ns/dname.php:4
 msgid "Delegation name"
 msgid "Delegation name"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:2
+#: pg-view/ns/edit.php:3
 msgid "Zone to be changed"
 msgid "Zone to be changed"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:12 pg-view/ns/print.php:20 pg-view/reg/print.php:11
+#: pg-view/ns/edit.php:13 pg-view/ns/print.php:21 pg-view/reg/edit.php:13
+#: pg-view/reg/print.php:5
 msgid "Display"
 msgid "Display"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:23
+#: pg-view/ns/edit.php:24
 #, php-format
 #, php-format
-msgid "New content of the %s zone"
+msgid "Authoritative records for %s"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:27
+#: pg-view/ns/edit.php:28 pg-view/reg/edit.php:28
 msgid "Replace"
 msgid "Replace"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:38
+#: pg-view/ns/edit.php:39
 msgid "Default values"
 msgid "Default values"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:40
+#: pg-view/ns/edit.php:41
 #, php-format
 #, php-format
 msgid "If the TTL is omitted, it will default to %s seconds."
 msgid "If the TTL is omitted, it will default to %s seconds."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:42
+#: pg-view/ns/edit.php:43 pg-view/reg/edit.php:41
 msgid "Precising the class (<code>IN</code>) is optional."
 msgid "Precising the class (<code>IN</code>) is optional."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:44
+#: pg-view/ns/edit.php:45
 msgid "Allowed values"
 msgid "Allowed values"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:46
+#: pg-view/ns/edit.php:47 pg-view/reg/edit.php:43
 #, php-format
 #, php-format
-msgid "Submitted zone content is limited to %s characters."
+msgid "Submitted field content is limited to %s characters."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:48
+#: pg-view/ns/edit.php:49
 #, php-format
 #, php-format
 msgid "TTLs must last between %1$s and %2$s seconds."
 msgid "TTLs must last between %1$s and %2$s seconds."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/edit.php:50
-msgid "The only types that can be defined are:"
+#: pg-view/ns/edit.php:51 pg-view/reg/edit.php:47
+msgid "The only types that can be defined here are:"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:1 pg-view/reg/ds.php:2 pg-view/reg/glue.php:2
-#: pg-view/reg/ns.php:2
+#: pg-view/ns/form.ns.php:2 pg-view/reg/select-action.inc.php:2
 msgid "Action"
 msgid "Action"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:3 pg-view/ns/zone-add.php:8 pg-view/reg/ds.php:4
-#: pg-view/reg/glue.php:4 pg-view/reg/ns.php:4
+#: pg-view/ns/form.ns.php:4 pg-view/ns/zone-add.php:9
+#: pg-view/reg/select-action.inc.php:4
 msgid "Add"
 msgid "Add"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:15 pg-view/ns/print.php:52 pg-view/ns/zone-del.php:2
+#: pg-view/ns/form.ns.php:16 pg-view/ns/print.php:53 pg-view/ns/zone-del.php:3
 msgid "Zone"
 msgid "Zone"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:29 pg-view/ns/print.php:33 pg-view/reg/print.php:17
+#: pg-view/ns/form.ns.php:31 pg-view/ns/print.php:34 pg-view/reg/print.php:11
 msgid "TTL"
 msgid "TTL"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:45
+#: pg-view/ns/form.ns.php:47
 msgid "Unit"
 msgid "Unit"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:48
+#: pg-view/ns/form.ns.php:50
 msgid "second"
 msgid "second"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:49
+#: pg-view/ns/form.ns.php:51
 msgid "minute"
 msgid "minute"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:50
+#: pg-view/ns/form.ns.php:52
 msgid "hour"
 msgid "hour"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/form.ns.php:51
+#: pg-view/ns/form.ns.php:53
 msgid "day"
 msgid "day"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/index.php:2
+#: pg-view/ns/index.php:3
 msgid "This service allows to host and manage DNS records inside a DNS zone."
 msgid "This service allows to host and manage DNS records inside a DNS zone."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/index.php:8
+#: pg-view/ns/index.php:9
 msgid "Currently hosted zones"
 msgid "Currently hosted zones"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/index.php:26
+#: pg-view/ns/index.php:27
 msgid "A zone hosted on this service is served by these name servers:"
 msgid "A zone hosted on this service is served by these name servers:"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/ip.php:3 pg-view/reg/glue.php:26
+#: pg-view/ns/ip.php:4 pg-view/reg/glue.php:15
 msgid "IP address"
 msgid "IP address"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:4
+#: pg-view/ns/loc.php:5
 msgid "Latitude"
 msgid "Latitude"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:6 pg-view/ns/loc.php:34
+#: pg-view/ns/loc.php:7 pg-view/ns/loc.php:35
 msgid "Degrees"
 msgid "Degrees"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:11 pg-view/ns/loc.php:39
+#: pg-view/ns/loc.php:12 pg-view/ns/loc.php:40
 msgid "Minutes"
 msgid "Minutes"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:16 pg-view/ns/loc.php:44
+#: pg-view/ns/loc.php:17 pg-view/ns/loc.php:45
 msgid "Seconds"
 msgid "Seconds"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:21 pg-view/ns/loc.php:49
+#: pg-view/ns/loc.php:22 pg-view/ns/loc.php:50
 msgid "Direction"
 msgid "Direction"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:25
+#: pg-view/ns/loc.php:26
 msgid "North"
 msgid "North"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:26
+#: pg-view/ns/loc.php:27
 msgid "South"
 msgid "South"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:32
+#: pg-view/ns/loc.php:33
 msgid "Longitude"
 msgid "Longitude"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:53
+#: pg-view/ns/loc.php:54
 msgid "East"
 msgid "East"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:54
+#: pg-view/ns/loc.php:55
 msgid "West"
 msgid "West"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:59
+#: pg-view/ns/loc.php:60
 msgid "Altitude"
 msgid "Altitude"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:63
+#: pg-view/ns/loc.php:64
 msgid "Size"
 msgid "Size"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:67
+#: pg-view/ns/loc.php:68
 msgid "Horizontal precision"
 msgid "Horizontal precision"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/loc.php:71
+#: pg-view/ns/loc.php:72
 msgid "Vertical precision"
 msgid "Vertical precision"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/mx.php:3 pg-view/ns/srv.php:4
+#: pg-view/ns/mx.php:4 pg-view/ns/srv.php:5
 msgid "Priority"
 msgid "Priority"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/mx.php:7
+#: pg-view/ns/mx.php:8
 msgid "Host"
 msgid "Host"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/ns.php:3 pg-view/reg/ns.php:18
+#: pg-view/ns/ns.php:4 pg-view/reg/ns.php:7
 msgid "Name server"
 msgid "Name server"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/print.php:3
+#: pg-view/ns/print.php:4
 msgid "Records table"
 msgid "Records table"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/print.php:6
+#: pg-view/ns/print.php:7
 msgid "DS record"
 msgid "DS record"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/print.php:9
+#: pg-view/ns/print.php:10
 msgid "Raw zonefile"
 msgid "Raw zonefile"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/print.php:11
+#: pg-view/ns/print.php:12
 msgid "Selected zone"
 msgid "Selected zone"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/print.php:34 pg-view/reg/print.php:18
+#: pg-view/ns/print.php:35 pg-view/reg/print.php:12
 msgid "Type"
 msgid "Type"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/print.php:60 pg-view/ns/sshfp.php:4 pg-view/reg/ds.php:22
+#: pg-view/ns/print.php:61 pg-view/ns/sshfp.php:5 pg-view/reg/ds.php:11
 msgid "Algorithm"
 msgid "Algorithm"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/print.php:64 pg-view/reg/ds.php:41
+#: pg-view/ns/print.php:65 pg-view/reg/ds.php:30
 msgid "Digest type"
 msgid "Digest type"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/print.php:68
+#: pg-view/ns/print.php:69
 msgid "Digest"
 msgid "Digest"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/srv.php:10
+#: pg-view/ns/srv.php:11
 msgid "Weight"
 msgid "Weight"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/srv.php:22
+#: pg-view/ns/srv.php:23
 msgid "Target"
 msgid "Target"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sshfp.php:15
+#: pg-view/ns/sshfp.php:16
 msgid "Hash type"
 msgid "Hash type"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sshfp.php:24
+#: pg-view/ns/sshfp.php:25
 msgid "Fingerprint"
 msgid "Fingerprint"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sync.php:2
+#: pg-view/ns/sync.php:3
 #, php-format
 #, php-format
 msgid "AAAA, A and CAA records are regularly copied from the source domain to the target domain. Their TTLs are set to %s seconds."
 msgid "AAAA, A and CAA records are regularly copied from the source domain to the target domain. Their TTLs are set to %s seconds."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sync.php:5
+#: pg-view/ns/sync.php:6
 msgid "Source domains that are not signed with DNSSEC are not synchronized. Synchronizations that remain broken may be deleted."
 msgid "Source domains that are not signed with DNSSEC are not synchronized. Synchronizations that remain broken may be deleted."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sync.php:8
+#: pg-view/ns/sync.php:9
 msgid "This is meant to be used for apex domains, where CNAME records are not allowed. For non-apex domains, CNAME records should be used instead."
 msgid "This is meant to be used for apex domains, where CNAME records are not allowed. For non-apex domains, CNAME records should be used instead."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sync.php:16
+#: pg-view/ns/sync.php:17
 msgid "Add new domain records to be synchronized"
 msgid "Add new domain records to be synchronized"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sync.php:16
+#: pg-view/ns/sync.php:17
 msgid "Synchronized domain"
 msgid "Synchronized domain"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sync.php:18
+#: pg-view/ns/sync.php:19
 msgid "Source domain"
 msgid "Source domain"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/sync.php:22
+#: pg-view/ns/sync.php:23
 msgid "Target domain"
 msgid "Target domain"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/tlsa.php:4
+#: pg-view/ns/tlsa.php:5
 msgid "Use"
 msgid "Use"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/tlsa.php:16
+#: pg-view/ns/tlsa.php:17
 msgid "Selector"
 msgid "Selector"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/tlsa.php:20
+#: pg-view/ns/tlsa.php:21
 msgid "the full certificate must match"
 msgid "the full certificate must match"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/tlsa.php:21
+#: pg-view/ns/tlsa.php:22
 msgid "the certificate public key must match"
 msgid "the certificate public key must match"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/tlsa.php:26
+#: pg-view/ns/tlsa.php:27
 msgid "Match type"
 msgid "Match type"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/tlsa.php:30
+#: pg-view/ns/tlsa.php:31
 msgid "full certificate"
 msgid "full certificate"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/txt.php:3
+#: pg-view/ns/txt.php:4
 msgid "Text"
 msgid "Text"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/txt.php:5
+#: pg-view/ns/txt.php:6
 msgid "Some text…"
 msgid "Some text…"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/zone-add.php:2
+#: pg-view/ns/zone-add.php:3
 #, php-format
 #, php-format
 msgid "To prove that you own this domain, it must have a NS record equal to %s when the form is being processed."
 msgid "To prove that you own this domain, it must have a NS record equal to %s when the form is being processed."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/ns/zone-del.php:11
+#: pg-view/ns/zone-del.php:12
 msgid "Delete everything related to this zone"
 msgid "Delete everything related to this zone"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/ds.php:18
+#: pg-view/reg/ds.php:7
 msgid "Key tag"
 msgid "Key tag"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/ds.php:52
+#: pg-view/reg/ds.php:41
 msgid "Key"
 msgid "Key"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/glue.php:27
+#: pg-view/reg/edit.php:3
+msgid "Domain to be changed"
+msgstr ""
+
+#: pg-view/reg/edit.php:24
+#, php-format
+msgid "Delegation records for %s"
+msgstr ""
+
+#: pg-view/reg/edit.php:39
+msgid "Input values"
+msgstr ""
+
+#: pg-view/reg/edit.php:45
+#, php-format
+msgid "TTL values are ignored and always set to %s seconds."
+msgstr ""
+
+#: pg-view/reg/glue.php:16
 #, php-format
 #, php-format
 msgid "%1$s or %2$s"
 msgid "%1$s or %2$s"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:2
+#: pg-view/reg/index.php:3
 #, php-format
 #, php-format
 msgid "This domain name registry allows to register domains ending with <code>%1$s</code>, for instance <code><em>domain</em>%1$s</code>."
 msgid "This domain name registry allows to register domains ending with <code>%1$s</code>, for instance <code><em>domain</em>%1$s</code>."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:7
+#: pg-view/reg/index.php:8
 msgid "Currently registered domains"
 msgid "Currently registered domains"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:27
+#: pg-view/reg/index.php:28
 msgid "Both <span aria-hidden=\"true\">⏳ </span><em>testing</em> and <span aria-hidden=\"true\">👤 </span><em>approved</em> accounts can register a domain under these suffixes:"
 msgid "Both <span aria-hidden=\"true\">⏳ </span><em>testing</em> and <span aria-hidden=\"true\">👤 </span><em>approved</em> accounts can register a domain under these suffixes:"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:38
+#: pg-view/reg/index.php:41
 msgid "Only <span aria-hidden=\"true\">👤 </span><em>approved</em> accounts can register a domain under these suffixes:"
 msgid "Only <span aria-hidden=\"true\">👤 </span><em>approved</em> accounts can register a domain under these suffixes:"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:49
+#: pg-view/reg/index.php:54
 msgid "Nobody can register a domain under these suffixes:"
 msgid "Nobody can register a domain under these suffixes:"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:63
+#: pg-view/reg/index.php:70
 msgid "Automatic updates from child zone"
 msgid "Automatic updates from child zone"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:64
+#: pg-view/reg/index.php:71
 msgid "CSYNC records"
 msgid "CSYNC records"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:66
+#: pg-view/reg/index.php:73
 msgid "The registry can synchronize NS records from the child zone if a CSYNC record is present at the apex of the child zone, has flags <code>1</code> and type bit map <code>NS</code>, and can be DNSSEC-validated. Others values are not supported."
 msgid "The registry can synchronize NS records from the child zone if a CSYNC record is present at the apex of the child zone, has flags <code>1</code> and type bit map <code>NS</code>, and can be DNSSEC-validated. Others values are not supported."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:68
+#: pg-view/reg/index.php:75
 msgid "DNSSEC and DS records"
 msgid "DNSSEC and DS records"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/index.php:70
+#: pg-view/reg/index.php:77
 msgid "Once DNSSEC has been manually enabled through the current interface, the delegated zone can publish a CDS record in order to update the DS record in the registry. A single CDS record with value <code>0 0 0 0</code> tells the registry to disable DNSSEC. Using a CDS record to enable DNSSEC is not supported."
 msgid "Once DNSSEC has been manually enabled through the current interface, the delegated zone can publish a CDS record in order to update the DS record in the registry. A single CDS record with value <code>0 0 0 0</code> tells the registry to disable DNSSEC. Using a CDS record to enable DNSSEC is not supported."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/register.php:2
+#: pg-view/reg/register.php:3
 msgid "Register a new domain on your account."
 msgid "Register a new domain on your account."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/register.php:18 pg-view/reg/transfer.php:14
+#: pg-view/reg/register.php:19 pg-view/reg/transfer.php:15
 msgid "Suffix"
 msgid "Suffix"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/register.php:31
+#: pg-view/reg/register.php:32
 msgid "Check availability"
 msgid "Check availability"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/register.php:33
+#: pg-view/reg/register.php:34
 msgid "Register"
 msgid "Register"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/transfer.php:2
+#: pg-view/reg/transfer.php:3
 #, php-format
 #, php-format
 msgid "To prove that you are allowed to receive the domain by its current owner, the domain must have an NS record equal to %s when the form is being processed. The NS record will be automatically deleted once validated."
 msgid "To prove that you are allowed to receive the domain by its current owner, the domain must have an NS record equal to %s when the form is being processed. The NS record will be automatically deleted once validated."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/transfer.php:7
+#: pg-view/reg/transfer.php:8
 msgid "Domain that will be transferred to this account"
 msgid "Domain that will be transferred to this account"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/transfer.php:26
+#: pg-view/reg/transfer.php:27
 msgid "Receive the domain"
 msgid "Receive the domain"
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/unregister.php:2
+#: pg-view/reg/unregister.php:3
 msgid "This will unregister the domain, making it registerable by anyone again (after a delay of 1 year plus half the registration period, with a maximum of 8 years)."
 msgid "This will unregister the domain, making it registerable by anyone again (after a delay of 1 year plus half the registration period, with a maximum of 8 years)."
 msgstr ""
 msgstr ""
 
 
-#: pg-view/reg/unregister.php:16
+#: pg-view/reg/unregister.php:17
 msgid "Unregister"
 msgid "Unregister"
 msgstr ""
 msgstr ""

+ 5 - 0
pages.php

@@ -63,6 +63,11 @@ define('PAGES', [
 			'description' => _('Print every record related to a domain and served by the registry'),
 			'description' => _('Print every record related to a domain and served by the registry'),
 			'tokens_account_cost' => 60,
 			'tokens_account_cost' => 60,
 		],
 		],
+		'edit' => [
+			'title' => _('Edit records'),
+			'description' => _('Set registry records to delegate a domain to chosen name servers'),
+			'tokens_account_cost' => 900,
+		],
 		'ns' => [
 		'ns' => [
 			'title' => sprintf(_('%s records'), '<abbr title="Name Server">NS</abbr>'),
 			'title' => sprintf(_('%s records'), '<abbr title="Name Server">NS</abbr>'),
 			'description' => sprintf(_('Indicate the name servers of a %s subdomain'), '<code>' . key(CONF['reg']['suffixes']) . '</code>'),
 			'description' => sprintf(_('Indicate the name servers of a %s subdomain'), '<code>' . key(CONF['reg']['suffixes']) . '</code>'),

+ 33 - 32
pg-act/ns/edit.php

@@ -1,60 +1,62 @@
 <?php declare(strict_types=1);
 <?php declare(strict_types=1);
 
 
-nsCheckZonePossession($_POST['zone']);
+nsCheckZonePossession($_POST['domain']);
 
 
-if (isset($_POST['zone-content'])) { // Update zone
+$path = CONF['ns']['knot_zones_path'] . '/' . $_POST['domain'] . 'zone';
+
+if (isset($_POST['records'])) {
 
 
 	// Get current SOA record
 	// Get current SOA record
-	$current_zone_content = file_get_contents(CONF['ns']['knot_zones_path'] . '/' . $_POST['zone'] . 'zone');
+	$current_zone_content = file_get_contents($path);
 	if ($current_zone_content === false)
 	if ($current_zone_content === false)
 		output(500, 'Unable to read zone file.');
 		output(500, 'Unable to read zone file.');
-	if (preg_match('/^(?<soa>' . preg_quote($_POST['zone'], '/') . '[\t ]+[0-9]{1,16}[\t ]+SOA[\t ]+.+)$/Dm', $current_zone_content, $matches) !== 1)
+	if (preg_match('/^(?<soa>' . preg_quote($_POST['domain'], '/') . '[\t ]+[0-9]{1,16}[\t ]+SOA[\t ]+.+)$/Dm', $current_zone_content, $matches) !== 1)
 		output(500, 'Unable to get current SOA record from zone file.');
 		output(500, 'Unable to get current SOA record from zone file.');
 
 
-	// Generate new zone content
+	// Generate new content
 	$new_zone_content = $matches['soa'] . LF;
 	$new_zone_content = $matches['soa'] . LF;
-	if (strlen($_POST['zone-content']) > ZONE_MAX_CHARACTERS)
-		output(403, sprintf(_('The zone is limited to %s characters.'), ZONE_MAX_CHARACTERS));
-	foreach (explode("\r\n", $_POST['zone-content']) as $line) {
-		if ($line === '') continue;
-		if (preg_match('/^(?<domain>[a-z0-9@._-]{1,256})(?:[\t ]+(?<ttl>[0-9]{1,16}))?(?:[\t ]+IN)?[\t ]+(?<type>[A-Z]{1,16})[\t ]+(?<value>.+)$/D', $line, $matches) !== 1)
-			output(403, _('The following line does not match the expected format: ') . '<code>' . htmlspecialchars($line) . '</code>');
-		if (in_array($matches['type'], ALLOWED_TYPES, true) !== true)
+	if (strlen($_POST['records']) > NS_TEXTAREA_MAX_CHARACTERS)
+		output(403, sprintf(_('The zone is limited to %s characters.'), NS_TEXTAREA_MAX_CHARACTERS));
+	foreach (explode("\r\n", $_POST['records']) as $record) {
+		if ($record === '') continue;
+		if (preg_match('/^(?<domain>[a-z0-9@._-]{1,256})(?:[\t ]+(?<ttl>[0-9]{1,16}))?(?:[\t ]+IN)?[\t ]+(?<type>[A-Z]{1,16})[\t ]+(?<value>.+)$/D', $record, $matches) !== 1)
+			output(403, _('The following line does not match the expected format: ') . '<code>' . htmlspecialchars($record) . '</code>');
+		if (in_array($matches['type'], NS_ALLOWED_TYPES, true) !== true)
 			output(403, sprintf(_('The %s type is not allowed.'), '<code>' . $matches['type'] . '</code>'));
 			output(403, sprintf(_('The %s type is not allowed.'), '<code>' . $matches['type'] . '</code>'));
-		if ($matches['ttl'] !== '' AND $matches['ttl'] < MIN_TTL)
-			output(403, sprintf(_('TTLs shorter than %s seconds are forbidden.'), MIN_TTL));
-		if ($matches['ttl'] !== '' AND $matches['ttl'] > MAX_TTL)
-			output(403, sprintf(_('TTLs longer than %s seconds are forbidden.'), MAX_TTL));
-		$new_zone_content .= $matches['domain'] . ' ' . (($matches['ttl'] === '') ? DEFAULT_TTL : $matches['ttl']) . ' ' . $matches['type'] . ' ' . $matches['value'] . LF;
+		if ($matches['ttl'] !== '' AND $matches['ttl'] < NS_MIN_TTL)
+			output(403, sprintf(_('TTLs shorter than %s seconds are forbidden.'), NS_MIN_TTL));
+		if ($matches['ttl'] !== '' AND $matches['ttl'] > NS_MAX_TTL)
+			output(403, sprintf(_('TTLs longer than %s seconds are forbidden.'), NS_MAX_TTL));
+		$new_zone_content .= $matches['domain'] . ' ' . (($matches['ttl'] === '') ? NS_DEFAULT_TTL : $matches['ttl']) . ' ' . $matches['type'] . ' ' . $matches['value'] . LF;
 	}
 	}
 
 
 	// Send the zone content to kzonecheck's stdin
 	// Send the zone content to kzonecheck's stdin
-	$process = proc_open(CONF['ns']['kzonecheck_path'] . ' --origin ' . $_POST['zone'] . ' --dnssec off -', [0 => ['pipe', 'r']], $pipes);
+	$process = proc_open(CONF['ns']['kzonecheck_path'] . ' --origin ' . escapeshellarg($_POST['domain']) . ' --dnssec off -', [0 => ['pipe', 'r']], $pipes);
 	if (is_resource($process) !== true)
 	if (is_resource($process) !== true)
 		output(500, 'Can\'t spawn kzonecheck.');
 		output(500, 'Can\'t spawn kzonecheck.');
 	fwrite($pipes[0], $new_zone_content);
 	fwrite($pipes[0], $new_zone_content);
 	fclose($pipes[0]);
 	fclose($pipes[0]);
 	if (proc_close($process) !== 0)
 	if (proc_close($process) !== 0)
-		output(403, _('Sent zone content is not correct (according to <code>kzonecheck</code>).'));
+		output(403, _('Sent content is not correct (according to <code>kzonecheck</code>).'));
 
 
 	ratelimit();
 	ratelimit();
 
 
-	knotc(['zone-freeze', $_POST['zone']], $output, $return_code);
+	knotc(['zone-freeze', $_POST['domain']], $output, $return_code);
 	if ($return_code !== 0)
 	if ($return_code !== 0)
 		output(500, 'Failed to freeze zone file.', $output);
 		output(500, 'Failed to freeze zone file.', $output);
 
 
-	knotc(['zone-flush', $_POST['zone']], $output, $return_code);
+	knotc(['zone-flush', $_POST['domain']], $output, $return_code);
 	if ($return_code !== 0)
 	if ($return_code !== 0)
 		output(500, 'Failed to flush zone file.', $output);
 		output(500, 'Failed to flush zone file.', $output);
 
 
-	if (file_put_contents(CONF['ns']['knot_zones_path'] . '/' . $_POST['zone'] . 'zone', $new_zone_content) === false)
+	if (file_put_contents($path, $new_zone_content) === false)
 		output(500, 'Failed to write zone file.');
 		output(500, 'Failed to write zone file.');
 
 
-	knotc(['zone-reload', $_POST['zone']], $output, $return_code);
+	knotc(['zone-reload', $_POST['domain']], $output, $return_code);
 	if ($return_code !== 0)
 	if ($return_code !== 0)
 		output(500, 'Failed to reload zone file.', $output);
 		output(500, 'Failed to reload zone file.', $output);
 
 
-	knotc(['zone-thaw', $_POST['zone']], $output, $return_code);
+	knotc(['zone-thaw', $_POST['domain']], $output, $return_code);
 	if ($return_code !== 0)
 	if ($return_code !== 0)
 		output(500, 'Failed to thaw zone file.', $output);
 		output(500, 'Failed to thaw zone file.', $output);
 
 
@@ -63,18 +65,17 @@ if (isset($_POST['zone-content'])) { // Update zone
 
 
 // Display zone
 // Display zone
 
 
-$zone_content = file_get_contents(CONF['ns']['knot_zones_path'] . '/' . $_POST['zone'] . 'zone');
-if ($zone_content === false)
+if (($records = file_get_contents($path)) === false)
 	output(500, 'Unable to read zone file.');
 	output(500, 'Unable to read zone file.');
 
 
-$data['zone_content'] = '';
-foreach (explode(LF, $zone_content) as $zone_line) {
+$data['records'] = '';
+foreach (explode(LF, $records) as $zone_line) {
 	if (empty($zone_line) OR str_starts_with($zone_line, ';'))
 	if (empty($zone_line) OR str_starts_with($zone_line, ';'))
 		continue;
 		continue;
-	if (preg_match('/^(?:(?:[a-z0-9_-]{1,63}\.){1,127})?' . preg_quote($_POST['zone'], '/') . '[\t ]+[0-9]{1,8}[\t ]+(?<type>[A-Z]{1,16})[\t ]+.+$/D', $zone_line, $matches)) {
-		if (in_array($matches['type'], ALLOWED_TYPES, true) !== true)
+	if (preg_match('/^(?:(?:[a-z0-9_-]{1,63}\.){1,127})?' . preg_quote($_POST['domain'], '/') . '[\t ]+[0-9]{1,8}[\t ]+(?<type>[A-Z]{1,16})[\t ]+.+$/D', $zone_line, $matches)) {
+		if (in_array($matches['type'], NS_ALLOWED_TYPES, true) !== true)
 			continue;
 			continue;
-		$data['zone_content'] .= $zone_line . LF;
+		$data['records'] .= $zone_line . LF;
 	}
 	}
 }
 }
-$data['zone_content'] .= LF;
+$data['records'] .= LF;

+ 6 - 6
pg-act/ns/zone-add.php

@@ -41,15 +41,15 @@ insert('zones', [
 $knotZonePath = CONF['ns']['knot_zones_path'] . '/' . $_POST['domain'] . 'zone';
 $knotZonePath = CONF['ns']['knot_zones_path'] . '/' . $_POST['domain'] . 'zone';
 $knotZone = implode(' ', [
 $knotZone = implode(' ', [
 	$_POST['domain'],
 	$_POST['domain'],
-	SOA_VALUES['ttl'],
+	NS_SOA_VALUES['ttl'],
 	'SOA',
 	'SOA',
 	CONF['ns']['servers'][0],
 	CONF['ns']['servers'][0],
-	SOA_VALUES['email'],
+	NS_SOA_VALUES['email'],
 	1,
 	1,
-	SOA_VALUES['refresh'],
-	SOA_VALUES['retry'],
-	SOA_VALUES['expire'],
-	SOA_VALUES['negative'],
+	NS_SOA_VALUES['refresh'],
+	NS_SOA_VALUES['retry'],
+	NS_SOA_VALUES['expire'],
+	NS_SOA_VALUES['negative'],
 ]) . LF;
 ]) . LF;
 foreach (CONF['ns']['servers'] as $server)
 foreach (CONF['ns']['servers'] as $server)
 	$knotZone .= $_POST['domain'] . ' 86400 NS ' . $server . LF;
 	$knotZone .= $_POST['domain'] . ' 86400 NS ' . $server . LF;

+ 4 - 22
pg-act/reg/ds.php

@@ -1,30 +1,12 @@
 <?php declare(strict_types=1);
 <?php declare(strict_types=1);
 
 
-if (!in_array($_POST['algo'], ['8', '13', '14', '15', '16'], true))
-	output(403, 'Wrong value for <code>algo</code>.');
-
-$_POST['keytag'] = intval($_POST['keytag']);
-if ((preg_match('/^[0-9]{1,6}$/D', $_POST['keytag'])) !== 1 OR !($_POST['keytag'] >= 1) OR !($_POST['keytag'] <= 65535))
-	output(403, 'Wrong value for <code>keytag</code>.');
-
-if ($_POST['dt'] !== '2' AND $_POST['dt'] !== '4')
-	output(403, 'Wrong value for <code>dt</code>.');
-
-if (preg_match('/^(?:[0-9a-fA-F]{64}|[0-9a-fA-F]{96})$/D', $_POST['key']) !== 1)
-	output(403, 'Wrong value for <code>key</code>.');
-
 regCheckDomainPossession($_POST['domain']);
 regCheckDomainPossession($_POST['domain']);
 
 
 rateLimit();
 rateLimit();
 
 
-knotcZoneExec(regParseDomain($_POST['domain'])['suffix'], [
-	$_POST['domain'],
-	CONF['reg']['ttl'],
-	'DS',
-	$_POST['keytag'],
-	$_POST['algo'],
-	$_POST['dt'],
-	$_POST['key']
-]);
+knotcZoneExec(regParseDomain($_POST['domain'])['suffix'], regParseRecord($_POST['domain'], [
+	'type' => 'DS',
+	...$_POST,
+]));
 
 
 output(200, _('Modification done.'));
 output(200, _('Modification done.'));

+ 97 - 0
pg-act/reg/edit.php

@@ -0,0 +1,97 @@
+<?php declare(strict_types=1);
+
+regCheckDomainPossession($_POST['domain']);
+
+$suffix = regParseDomain($_POST['domain'])['suffix'];
+
+$path = CONF['reg']['suffixes_path'] . '/' . $suffix . 'zone';
+
+if (isset($_POST['records'])) {
+
+	// Generate new content
+	$new_records = '';
+	if (strlen($_POST['records']) > REG_TEXTAREA_MAX_CHARACTERS)
+		output(403, sprintf(_('The zone is limited to %s characters.'), REG_TEXTAREA_MAX_CHARACTERS));
+	foreach (explode("\r\n", $_POST['records']) as $record) {
+		if ($record === '') continue;
+		if (preg_match('/^(?<domain>[a-z0-9@._-]{1,256})(?:[\t ]+(?<ttl>[0-9]{1,16}))?(?:[\t ]+IN)?[\t ]+(?<type>[A-Z]{1,16})[\t ]+(?<value>.+)$/D', $record, $matches) !== 1)
+			output(403, _('The following line does not match the expected format: ') . '<code>' . htmlspecialchars($record) . '</code>');
+		if (in_array($matches['type'], REG_ALLOWED_TYPES, true) !== true)
+			output(403, sprintf(_('The %s type is not allowed.'), '<code>' . $matches['type'] . '</code>'));
+		if ($matches['type'] === 'DS' AND count($record_values = explode(' ', $matches['value'])) !== 4)
+			output(403, _('A DS record expects 4 arguments.'));
+		$new_records .= implode(' ', regParseRecord($_POST['domain'], [
+			'domain' => $matches['domain'],
+			'type' => match ($matches['type']) {
+				'NS', 'DS' => $matches['type'],
+				'AAAA', 'A' => 'ip',
+				default => output(403, sprintf(_('The %s type is not allowed.'), '<code>' . $matches['type'] . '</code>')),
+			},
+			...match ($matches['type']) {
+				'NS' => ['ns' => $matches['value']],
+				'AAAA', 'A' => ['ip' => $matches['value']],
+				'DS' => array_combine([
+					'keytag',
+					'algo',
+					'dt',
+					'key',
+				], $record_values),
+			},
+		])) . LF;
+	}
+
+	// Send the zone content to kzonecheck's stdin
+	$process = proc_open(CONF['ns']['kzonecheck_path'] . ' --origin ' . escapeshellarg($suffix) . ' --dnssec off -', [0 => ['pipe', 'r']], $pipes);
+	if (is_resource($process) !== true)
+		output(500, 'Can\'t spawn kzonecheck.');
+	$new = $suffix . ' 10800 SOA invalid. invalid. 0 21600 7200 3628800 3600' . LF . $suffix . ' 10800 NS invalid.' . LF . $new_records;
+	fwrite($pipes[0], $new);
+	fclose($pipes[0]);
+	if (proc_close($process) !== 0)
+		output(403, _('Sent content is not correct (according to <code>kzonecheck</code>).'));
+
+	ratelimit();
+
+	knotc(['zone-freeze', $suffix], $output, $return_code);
+	if ($return_code !== 0)
+		output(500, 'Failed to freeze zone file.', $output);
+
+	knotc(['zone-flush', $suffix], $output, $return_code);
+	if ($return_code !== 0)
+		output(500, 'Failed to flush zone file.', $output);
+
+	if (($zone_content = file_get_contents($path)) === false)
+		output(500, 'Unable to read zone file.');
+
+	$zone_content = regStripDomain($_POST['domain'], $zone_content);
+
+	if (file_put_contents($path, $zone_content . LF . $new_records) === false)
+		output(500, 'Failed to write zone file.');
+
+	knotc(['zone-reload', $suffix], $output, $return_code);
+	if ($return_code !== 0)
+		output(500, 'Failed to reload zone file.', $output);
+
+	knotc(['zone-thaw', $suffix], $output, $return_code);
+	if ($return_code !== 0)
+		output(500, 'Failed to thaw zone file.', $output);
+
+	usleep(1000000);
+}
+
+// Display zone
+
+if (($records = file_get_contents($path)) === false)
+	output(500, 'Unable to read zone file.');
+
+$data['records'] = '';
+foreach (explode(LF, $records) as $zone_line) {
+	if (empty($zone_line) OR str_starts_with($zone_line, ';'))
+		continue;
+	if (preg_match('/^(?:(?:[a-z0-9_-]{1,63}\.){1,127})?' . preg_quote($_POST['domain'], '/') . '[\t ]+[0-9]{1,8}[\t ]+(?<type>[A-Z]{1,16})[\t ]+.+$/D', $zone_line, $matches)) {
+		if (in_array($matches['type'], REG_ALLOWED_TYPES, true) !== true)
+			continue;
+		$data['records'] .= $zone_line . LF;
+	}
+}
+$data['records'] .= LF;

+ 5 - 6
pg-act/reg/glue.php

@@ -4,11 +4,10 @@ regCheckDomainPossession($_POST['domain']);
 
 
 rateLimit();
 rateLimit();
 
 
-knotcZoneExec(regParseDomain($_POST['domain'])['suffix'], [
-	formatAbsoluteDomain(formatEndWithDot($_POST['subdomain']) . $_POST['domain']),
-	CONF['reg']['ttl'],
-	checkIpFormat($_POST['ip']),
-	$_POST['ip']
-]);
+knotcZoneExec(regParseDomain($_POST['domain'])['suffix'], regParseRecord($_POST['domain'], [
+	'type' => 'ip',
+	'domain' => formatAbsoluteDomain(formatEndWithDot($_POST['subdomain']) . $_POST['domain']),
+	...$_POST,
+]));
 
 
 output(200, _('Modification done.'));
 output(200, _('Modification done.'));

+ 4 - 6
pg-act/reg/ns.php

@@ -4,11 +4,9 @@ regCheckDomainPossession($_POST['domain']);
 
 
 rateLimit();
 rateLimit();
 
 
-knotcZoneExec(regParseDomain($_POST['domain'])['suffix'], [
-	$_POST['domain'],
-	CONF['reg']['ttl'],
-	'NS',
-	formatAbsoluteDomain($_POST['ns'])
-]);
+knotcZoneExec(regParseDomain($_POST['domain'])['suffix'], regParseRecord($_POST['domain'], [
+	'type' => 'NS',
+	...$_POST,
+]));
 
 
 output(200, _('Modification done.'));
 output(200, _('Modification done.'));

+ 13 - 13
pg-view/ns/edit.php

@@ -1,12 +1,12 @@
 <?php declare(strict_types=1); ?>
 <?php declare(strict_types=1); ?>
 <form method="post">
 <form method="post">
-	<label for="zone"><?= _('Zone to be changed') ?></label>
+	<label for="domain"><?= _('Zone to be changed') ?></label>
 	<br>
 	<br>
-	<select required="" name="zone" id="zone">
+	<select required="" name="domain" id="domain">
 		<option value="" disabled="" selected="">-</option>
 		<option value="" disabled="" selected="">-</option>
 <?php
 <?php
-foreach (nsListUserZones() as $zone)
-	echo '		<option value="' . $zone . '">' . $zone . '</option>' . LF;
+foreach (nsListUserZones() as $domain)
+	echo '		<option value="' . $domain . '">' . $domain . '</option>' . LF;
 ?>
 ?>
 	</select>
 	</select>
 	<br>
 	<br>
@@ -15,15 +15,15 @@ foreach (nsListUserZones() as $zone)
 
 
 <?php
 <?php
 
 
-if (isset($data['zone_content'])) { // Display zone
+if (isset($data['records'])) { // Display zone
 
 
 ?>
 ?>
 <form method="post">
 <form method="post">
-	<input type="hidden" name="zone" value="<?= $_POST['zone'] ?>">
+	<input type="hidden" name="domain" value="<?= $_POST['domain'] ?>">
 
 
-	<label for="zone-content"><?= sprintf(_('New content of the %s zone'), '<code><strong>' . $_POST['zone'] . '</strong></code>') ?></label>
+	<label for="zone-content"><?= sprintf(_('Authoritative records for %s'), '<code><strong>' . $_POST['domain'] . '</strong></code>') ?></label>
 	<br>
 	<br>
-	<textarea id="zone-content" name="zone-content" wrap="off" rows="<?= substr_count($data['zone_content'], LF) + 1 ?>"><?= htmlspecialchars($data['zone_content']) ?></textarea>
+	<textarea id="records" name="records" wrap="off" rows="<?= substr_count($data['records'], LF) + 1 ?>"><?= htmlspecialchars($data['records']) ?></textarea>
 	<br>
 	<br>
 	<input type="submit" value="<?= _('Replace') ?>">
 	<input type="submit" value="<?= _('Replace') ?>">
 </form>
 </form>
@@ -38,21 +38,21 @@ displayFinalMessage($data);
 
 
 <h2><?= _('Default values') ?></h2>
 <h2><?= _('Default values') ?></h2>
 
 
-<p><?= sprintf(_('If the TTL is omitted, it will default to %s seconds.'), '<code><time datetime="PT' . DEFAULT_TTL . 'S">' . DEFAULT_TTL . '</time></code>') ?></p>
+<p><?= sprintf(_('If the TTL is omitted, it will default to %s seconds.'), '<code><time datetime="PT' . NS_DEFAULT_TTL . 'S">' . NS_DEFAULT_TTL . '</time></code>') ?></p>
 
 
 <p><?= _('Precising the class (<code>IN</code>) is optional.') ?></p>
 <p><?= _('Precising the class (<code>IN</code>) is optional.') ?></p>
 
 
 <h2><?= _('Allowed values') ?></h2>
 <h2><?= _('Allowed values') ?></h2>
 
 
-<p><?= sprintf(_('Submitted zone content is limited to %s characters.'), ZONE_MAX_CHARACTERS) ?></p>
+<p><?= sprintf(_('Submitted field content is limited to %s characters.'), NS_TEXTAREA_MAX_CHARACTERS) ?></p>
 
 
-<p><?= sprintf(_('TTLs must last between %1$s and %2$s seconds.'), '<code><time datetime="PT' . MIN_TTL . 'S">' . MIN_TTL . '</time></code>', '<code><time datetime="PT' . MAX_TTL . 'S">' . MAX_TTL . '</time></code>') ?></p>
+<p><?= sprintf(_('TTLs must last between %1$s and %2$s seconds.'), '<code><time datetime="PT' . NS_MIN_TTL . 'S">' . NS_MIN_TTL . '</time></code>', '<code><time datetime="PT' . NS_MAX_TTL . 'S">' . NS_MAX_TTL . '</time></code>') ?></p>
 
 
-<p><?= _('The only types that can be defined are:') ?></p>
+<p><?= _('The only types that can be defined here are:') ?></p>
 
 
 <ul>
 <ul>
 <?php
 <?php
-	foreach (ALLOWED_TYPES as $allowed_type)
+	foreach (NS_ALLOWED_TYPES as $allowed_type)
 		echo '	<li><code>' . $allowed_type . '</code></li>';
 		echo '	<li><code>' . $allowed_type . '</code></li>';
 ?>
 ?>
 </ul>
 </ul>

+ 1 - 1
pg-view/ns/form.ns.php

@@ -32,7 +32,7 @@ foreach ($user_zones as $zone)
 		<div>
 		<div>
 			<label for="ttl-value"><?= _('Value') ?></label>
 			<label for="ttl-value"><?= _('Value') ?></label>
 			<br>
 			<br>
-			<input required="" id="ttl-value" list="ttls" name="ttl-value" size="6" type="number" min="1" max="432000" value="<?= $_POST['ttl-value'] ?? DEFAULT_TTL ?>" placeholder="<?= DEFAULT_TTL ?>">
+			<input required="" id="ttl-value" list="ttls" name="ttl-value" size="6" type="number" min="1" max="432000" value="<?= $_POST['ttl-value'] ?? NS_DEFAULT_TTL ?>" placeholder="<?= NS_DEFAULT_TTL ?>">
 			<datalist id="ttls">
 			<datalist id="ttls">
 				<option value="900">
 				<option value="900">
 				<option value="1800">
 				<option value="1800">

+ 54 - 0
pg-view/reg/edit.php

@@ -0,0 +1,54 @@
+<?php declare(strict_types=1); ?>
+<form method="post">
+	<label for="domain"><?= _('Domain to be changed') ?></label>
+	<br>
+	<select required="" name="domain" id="domain">
+		<option value="" disabled="" selected="">-</option>
+<?php
+foreach (regListUserDomains() as $domain)
+	echo '		<option value="' . $domain . '">' . $domain . '</option>' . LF;
+?>
+	</select>
+	<br>
+	<input type="submit" value="<?= _('Display') ?>">
+</form>
+
+<?php
+
+if (isset($data['records'])) { // Display zone
+
+?>
+<form method="post">
+	<input type="hidden" name="domain" value="<?= $_POST['domain'] ?>">
+
+	<label for="records"><?= sprintf(_('Delegation records for %s'), '<code><strong>' . $_POST['domain'] . '</strong></code>') ?></label>
+	<br>
+	<textarea id="records" name="records" wrap="off" rows="<?= substr_count($data['records'], LF) + 1 ?>"><?= htmlspecialchars($data['records']) ?></textarea>
+	<br>
+	<input type="submit" value="<?= _('Replace') ?>">
+</form>
+
+<?php
+
+}
+
+displayFinalMessage($data);
+
+?>
+
+<h2><?= _('Input values') ?></h2>
+
+<p><?= _('Precising the class (<code>IN</code>) is optional.') ?></p>
+
+<p><?= sprintf(_('Submitted field content is limited to %s characters.'), REG_TEXTAREA_MAX_CHARACTERS) ?></p>
+
+<p><?= sprintf(_('TTL values are ignored and always set to %s seconds.'), '<code><time datetime="PT' . CONF['reg']['ttl'] . 'S">' . CONF['reg']['ttl'] . '</time></code>') ?></p>
+
+<p><?= _('The only types that can be defined here are:') ?></p>
+
+<ul>
+<?php
+	foreach (REG_ALLOWED_TYPES as $allowed_type)
+		echo '	<li><code>' . $allowed_type . '</code></li>';
+?>
+</ul>