From 7bdb8d1c0e360c967fa3ff4808f2ba5bebfc3fe6 Mon Sep 17 00:00:00 2001
From: ftimme <ft@falkotimme.com>
Date: Sat, 3 Dec 2005 10:56:08 +0000
Subject: [PATCH]

---
 interface/lib/classes/validate_dns.inc.php | 260 +++++++++++++++++++++
 interface/web/dns/form/rr.tform.php        |   4 +
 interface/web/dns/form/soa.tform.php       |  22 +-
 interface/web/dns/lib/lang/en_rr.lng       |  28 +++
 interface/web/dns/lib/lang/en_soa.lng      |  21 ++
 interface/web/dns/rr_edit.php              |   3 +
 interface/web/dns/soa_edit.php             |   3 +
 7 files changed, 337 insertions(+), 4 deletions(-)
 create mode 100644 interface/lib/classes/validate_dns.inc.php

diff --git a/interface/lib/classes/validate_dns.inc.php b/interface/lib/classes/validate_dns.inc.php
new file mode 100644
index 000000000..bca195fe3
--- /dev/null
+++ b/interface/lib/classes/validate_dns.inc.php
@@ -0,0 +1,260 @@
+<?php
+
+/*
+Copyright (c) 2005, Till Brehm, Falko Timme, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of ISPConfig nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+* DNS validation
+*
+* @author Falko Timme <ft@falkotimme.com>
+* @copyright Copyright &copy; 2005, Falko Timme
+*/
+
+class validate_dns {
+
+function validate_field($field, $area, $zoneid, $wildcard_allowed = 1){
+  //$desc: Name, Data, RP mbox, RP txtref, SRV target, Zone origin, Name server, Admin email
+  global $app, $conf;
+
+  switch ($area) {
+  case "Name":
+    $desc = $app->tform->wordbook['name_txt'];
+    break;
+  case "Data":
+    $desc = $app->tform->wordbook['data_txt'];
+    break;
+  case "RP mbox":
+    $desc = $app->tform->wordbook['rp_mbox_txt'];
+    break;
+  case "RP txtref":
+    $desc = $app->tform->wordbook['rp_txtref_txt'];
+    break;
+  case "SRV target":
+    $desc = $app->tform->wordbook['srv_target_txt'];
+    break;
+  case "Zone origin":
+    $desc = $app->tform->wordbook['zone_origin_txt'];
+    break;
+  case "Name server":
+    $desc = $app->tform->wordbook['ns_txt'];
+    break;
+  case "Admin email":
+    $desc = $app->tform->wordbook['mbox_txt'];
+    break;
+  }
+
+  $error = '';
+
+  $valid_characters = "*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_";
+
+  if(strlen($field) > 255) $error .= $desc." ".$app->tform->wordbook['error_255_characters']."<br>\r\n";
+
+  $parts = explode(".", $field);
+  $i = 0;
+  foreach ($parts as $part){
+    $i++;
+
+    if(strlen($part) > 63) $error .= $desc." ".$app->tform->wordbook['error_63_characters']."<br>\r\n";
+
+    if(strspn($part, $valid_characters) != strlen($part)) $error .= $desc." ".$app->tform->wordbook['error_invalid_characters']."<br>\r\n";
+
+    if(substr($part, 0, 1) == '-') $error .= $desc." ".$app->tform->wordbook['error_hyphen_begin']."<br>\r\n";
+    if(substr($part, -1) == '-') $error .= $desc." ".$app->tform->wordbook['error_hyphen_end']."<br>\r\n";
+
+    if(strstr($part, "*")){
+      if($wildcard_allowed){
+        if($i != 1) $error .= $desc." ".$app->tform->wordbook['error_wildcard_non_initial_part']."<br>\r\n";
+
+        if($part != "*") $error .= $desc." ".$app->tform->wordbook['error_wildcard_mix']."<br>\r\n";
+      } else {
+        $error .= $desc." ".$app->tform->wordbook['error_no_wildcard_allowed']."<br>\r\n";
+      }
+    }
+  }
+
+  if(substr($field, -1) == '.' && $area == 'Name'){
+    $soa = $app->db->queryOneRecord("SELECT * FROM soa WHERE id = ".$zoneid);
+    if(substr($field, (strlen($field) - strlen($soa['origin']))) != $soa['origin']) $error .= $desc." ".$app->tform->wordbook['error_out_of_zone']."<br>\r\n";
+  }
+
+  return $error;
+}
+
+function validate_rp_data(&$data, $zoneid){
+  global $app, $conf;
+  $error = '';
+  $fields = explode(" ", trim($data));
+  if(count($fields) != 2) return $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_invalid_rp']."<br>\r\n";
+  $mbox = $fields[0];
+  $txtref = $fields[1];
+
+  $error .= $this->validate_field($mbox, 'RP mbox', $zoneid, 0);
+  $error .= $this->validate_field($txtref, 'RP txtref', $zoneid, 0);
+
+  $data = $mbox." ".$txtref;
+  return $error;
+}
+
+function validate_srv_data(&$data, $zoneid){
+  global $app, $conf;
+  $error = '';
+
+  $fields = explode(" ", trim($data));
+  if(count($fields) != 3) return $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_invalid_srv']."<br>\r\n";
+
+  $weight = $fields[0];
+  $port = $fields[1];
+  $target = $fields[2];
+  if($weight < 0 || $weight > 65535) $error .= $app->tform->wordbook['weight_txt']." (\"<i>" . htmlentities($weight)."</i>\") ".$app->tform->wordbook['error_srv_out_of_range']."<br>\r\n";
+  if ($port < 0 || $port > 65535) $error .= $app->tform->wordbook['port_txt']." (\"<i>".htmlentities($port)."</i>\") ".$app->tform->wordbook['error_srv_out_of_range']."<br>\r\n";
+
+  $error .= $this->validate_field($target, "SRV target", $zoneid, 0);
+
+  $data = (int)$weight." ".(int)$port." ".$target;
+  return $error;
+}
+
+function is_integer($value, $fieldname, $zero_allowed = 0){
+  global $app, $conf;
+
+  $error = '';
+
+  if(intval($value) != $value || !is_numeric($value)) $error .= $fieldname." ".$app->tform->wordbook['error_must_be_integer']."<br>\r\n";
+  if($value > 2147483647) $error .= $fieldname." ".$app->tform->wordbook['error_must_not_be_greater_than_2147483647']."<br>\r\n";
+  if(!$zero_allowed){
+    if($value <= 0) $error .= $fieldname." ".$app->tform->wordbook['error_must_be_positive']."<br>\r\n";
+  } else {
+    if($value < 0) $error .= $fieldname." ".$app->tform->wordbook['error_must_not_be_negative']."<br>\r\n";
+  }
+
+  return $error;
+}
+
+function validate_rr(&$rr){
+  global $app, $conf;
+
+  $error = '';
+
+  $tmp_rr = $rr;
+  foreach($tmp_rr as $key => $val){
+    $rr[$key] = trim($val);
+  }
+  unset($tmp_rr);
+
+  $error .= $this->validate_field($rr['name'], 'Name', $rr['zone'], 1);
+
+  switch ($rr['type']) {
+  case "A":
+    $ip_parts = explode(".", $rr['data']);
+    if(count($ip_parts) != 4){
+      $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_a']."<br>\r\n";
+    } else {
+      for($n = 0; $n < 4; $n++){
+        $q = $ip_parts[$n];
+        if(!is_numeric($q) || (int)$q < 0 || (int)$q > 255) $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_a']."<br>\r\n";
+      }
+    }
+    $rr['data'] = (int)$ip_parts[0].".".(int)$ip_parts[1].".".(int)$ip_parts[2].".".(int)$ip_parts[3];
+    break;
+  case "AAAA":
+    $valid_chars = "ABCDEFabcdef1234567890:";
+
+    if(strspn($rr['data'], $valid_chars) != strlen($rr['data'])) $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_aaaa']."<br>\r\n";
+    break;
+  case "ALIAS":
+    $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
+    break;
+  case "CNAME":
+    $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
+    break;
+  case "HINFO":
+    if(!strchr($rr['data'], ' ')) $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_hinfo']."<br>\r\n";
+    break;
+  case "MX":
+    $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
+    break;
+  case "NS":
+    $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
+    break;
+  case "PTR":
+    $error .= $this->validate_field($rr['data'], 'Data', $rr['zone'], 0);
+    if(substr($rr['data'], -1) != '.') $error .= $app->tform->wordbook['data_txt']." ".$app->tform->wordbook['error_ptr']."<br>\r\n";
+    break;
+  case "RP":
+    $error .= $this->validate_rp_data($rr['data'], $rr['zone']);
+    break;
+  case "SRV":
+    $error .= $this->validate_srv_data($rr['data'], $rr['zone']);
+    break;
+  case "TXT":
+    break;
+  }
+
+  $error .= $this->is_integer($rr['aux'], $app->tform->wordbook['aux_txt'], 1);
+
+  $error .= $this->is_integer($rr['ttl'], $app->tform->wordbook['ttl_txt']);
+
+
+  return $error;
+}
+
+function validate_soa(&$soa){
+  global $app, $conf;
+
+  $error = '';
+
+  $tmp_soa = $soa;
+  foreach($tmp_soa as $key => $val){
+    if($key != 'active') $soa[$key] = trim($val);
+  }
+  unset($tmp_soa);
+
+  if($soa['origin'] == '') $error .= $app->tform->wordbook['origin_txt']." ".$app->tform->wordbook['error_empty']."<br>\r\n";
+  if(substr($soa['origin'], -1) != '.') $error .= $app->tform->wordbook['origin_txt']." ".$app->tform->wordbook['error_dot']."<br>\r\n";
+  $error .= $this->validate_field($soa['origin'], "Zone origin", $soa['id'], 0);
+
+  $error .= $this->is_integer($soa['ttl'], $app->tform->wordbook['ttl_txt']);
+
+  if($soa['ns'] == '') $error .= $app->tform->wordbook['ns_txt']." ".$app->tform->wordbook['error_empty']."<br>\r\n";
+  $error .= $this->validate_field($soa['ns'], "Name server", $soa['id'], 0);
+
+  if($soa['mbox'] == '') $error .= $app->tform->wordbook['mbox_txt']." ".$app->tform->wordbook['error_empty']."<br>\r\n";
+  $error .= $this->validate_field($soa['mbox'], "Admin email", $soa['id'], 0);
+
+  $error .= $this->is_integer($soa['refresh'], $app->tform->wordbook['refresh_txt']);
+
+  $error .= $this->is_integer($soa['retry'], $app->tform->wordbook['retry_txt']);
+
+  $error .= $this->is_integer($soa['expire'], $app->tform->wordbook['expire_txt']);
+
+  $error .= $this->is_integer($soa['minimum'], $app->tform->wordbook['minimum_txt']);
+
+  return $error;
+}
+
+}
\ No newline at end of file
diff --git a/interface/web/dns/form/rr.tform.php b/interface/web/dns/form/rr.tform.php
index 1f299260b..e9af9906b 100644
--- a/interface/web/dns/form/rr.tform.php
+++ b/interface/web/dns/form/rr.tform.php
@@ -110,9 +110,11 @@ $form["tabs"]['rr'] = array (
                 'aux' => array (
                         'datatype'        => 'INTEGER',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ('type' => 'ISINT',
                                                                 'errmsg'=> 'rr_aux_error_noint'),
                                                    ),
+                        */
                         'default'        => '',
                         'value'                => '',
                         'width'                => '30',
@@ -121,9 +123,11 @@ $form["tabs"]['rr'] = array (
                 'ttl' => array (
                         'datatype'        => 'INTEGER',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ('type' => 'ISPOSITIVE',
                                                                 'errmsg'=> 'rr_ttl_error_notpositive'),
                                                    ),
+                        */
                         'default'        => '86400',
                         'value'                => '86400',
                         'width'                => '30',
diff --git a/interface/web/dns/form/soa.tform.php b/interface/web/dns/form/soa.tform.php
index 9b39b6ad1..ca23e195d 100644
--- a/interface/web/dns/form/soa.tform.php
+++ b/interface/web/dns/form/soa.tform.php
@@ -74,11 +74,9 @@ $form["tabs"]['soa'] = array (
                 'origin' => array (
                         'datatype'        => 'VARCHAR',
                         'formtype'        => 'TEXT',
-                        'validators'      => array (0 => array ( 'type'        => 'NOTEMPTY',
-                                                                   'errmsg'=> 'soa_error_empty'),
-                                                      1 => array ( 'type'        => 'UNIQUE',
+                        'validators'      => array (0 => array ( 'type'        => 'UNIQUE',
                                                                    'errmsg'=> 'soa_error_unique'),
-                                                                        ),
+                                                   ),
                         'default'         => '',
                         'value'           => '',
                         'width'           => '30',
@@ -87,9 +85,11 @@ $form["tabs"]['soa'] = array (
                 'ns' => array (
                         'datatype'        => 'VARCHAR',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ( 'type'        => 'NOTEMPTY',
                                                                    'errmsg'=> 'ns_error_empty'),
                                                     ),
+                        */
                         'default'         => $conf['default_ns'],
                         'value'           => $conf['default_ns'],
                         'width'           => '30',
@@ -98,9 +98,11 @@ $form["tabs"]['soa'] = array (
                 'mbox' => array (
                         'datatype'        => 'VARCHAR',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ( 'type'        => 'NOTEMPTY',
                                                                    'errmsg'=> 'mbox_error_empty'),
                                                     ),
+                        */
                         'default'         => $conf['default_mbox'],
                         'value'           => $conf['default_mbox'],
                         'width'           => '30',
@@ -109,9 +111,11 @@ $form["tabs"]['soa'] = array (
                 'serial' => array (
                         'datatype'        => 'INTEGER',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ( 'type'        => 'ISPOSITIVE',
                                                                    'errmsg'=> 'serial_error_notpositive'),
                                                     ),
+                        */
                         'default'         => date("Ymd").'01',
                         'value'           => date("Ymd").'01',
                         'width'           => '30',
@@ -120,9 +124,11 @@ $form["tabs"]['soa'] = array (
                 'refresh' => array (
                         'datatype'        => 'INTEGER',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ( 'type'        => 'ISPOSITIVE',
                                                                    'errmsg'=> 'refresh_error_notpositive'),
                                                     ),
+                        */
                         'default'         => $conf['default_refresh'],
                         'value'           => $conf['default_refresh'],
                         'width'           => '30',
@@ -131,9 +137,11 @@ $form["tabs"]['soa'] = array (
                 'retry' => array (
                         'datatype'        => 'INTEGER',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ( 'type'        => 'ISPOSITIVE',
                                                                    'errmsg'=> 'retry_error_notpositive'),
                                                    ),
+                        */
                         'default'         => $conf['default_retry'],
                         'value'           => $conf['default_retry'],
                         'width'           => '30',
@@ -142,9 +150,11 @@ $form["tabs"]['soa'] = array (
                 'expire' => array (
                         'datatype'        => 'INTEGER',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ( 'type'        => 'ISPOSITIVE',
                                                                    'errmsg'=> 'expire_error_notpositive'),
                                                    ),
+                        */
                         'default'         => $conf['default_expire'],
                         'value'           => $conf['default_expire'],
                         'width'           => '30',
@@ -153,9 +163,11 @@ $form["tabs"]['soa'] = array (
                 'minimum' => array (
                         'datatype'        => 'INTEGER',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ( 'type'        => 'ISPOSITIVE',
                                                                    'errmsg'=> 'minimum_error_notpositive'),
                                                    ),
+                        */
                         'default'         => $conf['default_minimum_ttl'],
                         'value'           => $conf['default_minimum_ttl'],
                         'width'           => '30',
@@ -164,9 +176,11 @@ $form["tabs"]['soa'] = array (
                 'ttl' => array (
                         'datatype'        => 'INTEGER',
                         'formtype'        => 'TEXT',
+                        /*
                         'validators'      => array (0 => array ( 'type'        => 'ISPOSITIVE',
                                                                    'errmsg'=> 'ttl_error_notpositive'),
                                                    ),
+                        */
                         'default'         => $conf['default_ttl'],
                         'value'           => $conf['default_ttl'],
                         'width'           => '30',
diff --git a/interface/web/dns/lib/lang/en_rr.lng b/interface/web/dns/lib/lang/en_rr.lng
index a835ac60d..33c4d34aa 100644
--- a/interface/web/dns/lib/lang/en_rr.lng
+++ b/interface/web/dns/lib/lang/en_rr.lng
@@ -5,9 +5,37 @@ $wb["type_txt"] = 'Type';
 $wb["data_txt"] = 'Data';
 $wb["aux_txt"] = 'Preference/Priority';
 $wb["ttl_txt"] = 'TTL';
+$wb["weight_txt"] = 'Weight';
+$wb["port_txt"] = 'Port';
+$wb["rp_mbox_txt"] = 'RP Mailbox';
+$wb["rp_txtref_txt"] = 'RP TXTREF';
+$wb["srv_target_txt"] = 'SRV TARGET';
+$wb["zone_origin_txt"] = 'Zone Origin';
+$wb["ns_txt"] = 'Name Server';
+$wb["mbox_txt"] = 'Admin Email';
 $wb["btn_save_txt"] = 'Save';
 $wb["btn_cancel_txt"] = 'Cancel';
 $wb["rr_data_error_empty"] = 'The data field must not be empty!';
 $wb["rr_aux_error_noint"] = 'Preference/priority must be an integer!';
 $wb["rr_ttl_error_notpositive"] = 'The TTL must be positive!';
+$wb["error_ptr"] = 'must contain a fully qualified domain name, ending with a dot!';
+$wb["error_hinfo"] = 'must contain the CPU type, then a space, then the OS type!';
+$wb["error_aaaa"] = 'must contain a valid IPv6 address!';
+$wb["error_a"] = 'must contain a valid IP address!';
+$wb["error_must_be_integer"] = 'must be an integer!';
+$wb["error_must_not_be_greater_than_2147483647"] = 'must not be greater than 2147483647!';
+$wb["error_must_be_positive"] = 'must be positive!';
+$wb["error_must_not_be_negative"] = 'must not be negative!';
+$wb["error_255_characters"] = 'contains more than 255 characters!';
+$wb["error_63_characters"] = 'contains a part with more than 63 characters!';
+$wb["error_invalid_characters"] = 'contains a part with invalid characters!';
+$wb["error_hyphen_begin"] = 'contains a part that begins with a hyphen!';
+$wb["error_hyphen_end"] = 'contains a part that ends with a hyphen!';
+$wb["error_wildcard_non_initial_part"] = 'contains a wildcard in a non-initial part!';
+$wb["error_wildcard_mix"] = 'contains a part mixing a wildcard character with other data!';
+$wb["error_no_wildcard_allowed"] = 'must not contain wildcards!';
+$wb["error_out_of_zone"] = 'is out of zone!';
+$wb["error_invalid_rp"] = 'has invalid format. The correct format is the <i>mbox</i> (a DNS-encoded email address), then a space, then the <i>txtref</i>, which should contain either a host for TXT lookup or a dot!';
+$wb["error_invalid_srv"] = 'has invalid format.  The correct format is the <i>weight</i> (0-65535), then a space, then the <i>port</i> (0-65535), then a space, then the <i>target</i>!';
+$wb["error_srv_out_of_range"] = 'for SRV record is out of range!';
 ?>
\ No newline at end of file
diff --git a/interface/web/dns/lib/lang/en_soa.lng b/interface/web/dns/lib/lang/en_soa.lng
index e5bb800dc..7e8b1ebc7 100644
--- a/interface/web/dns/lib/lang/en_soa.lng
+++ b/interface/web/dns/lib/lang/en_soa.lng
@@ -10,6 +10,12 @@ $wb["minimum_txt"] = 'Minimum TTL';
 $wb["ttl_txt"] = 'TTL';
 $wb["active_txt"] = 'Active';
 $wb["xfer_txt"] = 'Zone Transfers';
+$wb["name_txt"] = 'Name';
+$wb["data_txt"] = 'Data';
+$wb["rp_mbox_txt"] = 'RP Mailbox';
+$wb["rp_txtref_txt"] = 'RP TXTREF';
+$wb["srv_target_txt"] = 'SRV TARGET';
+$wb["zone_origin_txt"] = 'Zone Origin';
 $wb["btn_save_txt"] = 'Save';
 $wb["btn_cancel_txt"] = 'Cancel';
 $wb["soa_error_empty"] = 'The origin must not be empty!';
@@ -22,4 +28,19 @@ $wb["retry_error_notpositive"] = 'The retry must be positive!';
 $wb["expire_error_notpositive"] = 'The expire must be positive!';
 $wb["minimum_error_notpositive"] = 'The minimum TTL must be positive!';
 $wb["ttl_error_notpositive"] = 'The TTL must be positive!';
+$wb["error_empty"] = 'must not be empty!';
+$wb["error_dot"] = 'must end with a dot!';
+$wb["error_must_be_integer"] = 'must be an integer!';
+$wb["error_must_not_be_greater_than_2147483647"] = 'must not be greater than 2147483647!';
+$wb["error_must_be_positive"] = 'must be positive!';
+$wb["error_must_not_be_negative"] = 'must not be negative!';
+$wb["error_255_characters"] = 'contains more than 255 characters!';
+$wb["error_63_characters"] = 'contains a part with more than 63 characters!';
+$wb["error_invalid_characters"] = 'contains a part with invalid characters!';
+$wb["error_hyphen_begin"] = 'contains a part that begins with a hyphen!';
+$wb["error_hyphen_end"] = 'contains a part that ends with a hyphen!';
+$wb["error_wildcard_non_initial_part"] = 'contains a wildcard in a non-initial part!';
+$wb["error_wildcard_mix"] = 'contains a part mixing a wildcard character with other data!';
+$wb["error_no_wildcard_allowed"] = 'must not contain wildcards!';
+$wb["error_out_of_zone"] = 'is out of zone!';
 ?>
\ No newline at end of file
diff --git a/interface/web/dns/rr_edit.php b/interface/web/dns/rr_edit.php
index 582fec8e3..ff8590d93 100644
--- a/interface/web/dns/rr_edit.php
+++ b/interface/web/dns/rr_edit.php
@@ -58,6 +58,9 @@ class page_action extends tform_actions {
 
                 $this->dataRecord["zone"] = $_SESSION['s']['list']['rr']['parent_id'];
 
+                $app->uses('validate_dns');
+                $app->tform->errorMessage .= $app->validate_dns->validate_rr($this->dataRecord);
+
                 // update serial
                 $soa = $app->db->queryOneRecord("SELECT * FROM soa WHERE id = ".$this->dataRecord["zone"]);
                 $serial = $soa['serial'];
diff --git a/interface/web/dns/soa_edit.php b/interface/web/dns/soa_edit.php
index 4f3179b9f..77fc41785 100644
--- a/interface/web/dns/soa_edit.php
+++ b/interface/web/dns/soa_edit.php
@@ -56,6 +56,9 @@ class page_action extends tform_actions {
         function onSubmit() {
                 global $app, $conf;
 
+                $app->uses('validate_dns');
+                $app->tform->errorMessage .= $app->validate_dns->validate_soa($this->dataRecord);
+
                 // update serial
                 $soa = $app->db->queryOneRecord("SELECT * FROM soa WHERE id = ".$this->dataRecord["id"]);
                 $serial = $soa['serial'];
-- 
GitLab