diff --git a/includes/class/Zone.php b/includes/class/Zone.php index ffc5588..a429550 100644 --- a/includes/class/Zone.php +++ b/includes/class/Zone.php @@ -26,10 +26,10 @@ class Zone { $this->setAccount($data['account']); $this->setSerial($data['serial']); $this->url = $data['url']; - if (isset($data['soa_edit'])) + if (isset($data['soa_edit']) && $data['soa_edit'] != "") $this->setSoaEdit($data['soa_edit']); - if (isset($data['soa_edit_api'])) - $this->setSoaEditApi($data['soa_edit_api']); + if (isset($data['soa_edit_api']) && $data['soa_edit_api'] != "") + $this->setSoaEditApi($data['soa_edit_api'], True); foreach ($data['masters'] as $master) { $this->addMaster($master); @@ -76,7 +76,12 @@ class Zone { $this->soa_edit = $soaedit; } - public function setSoaEditApi($soaeditapi) { + public function setSoaEditApi($soaeditapi, $overwrite=False) { + if (isset($this->soa_edit_api) and $this->soa_edit_api != "") { + if ($overwrite === False) { + return False; + } + } $this->soa_edit_api = $soaeditapi; } public function setName($name) { @@ -181,8 +186,12 @@ class Zone { $ret['nameservers'] = $this->nameservers; $ret['kind'] = $this->kind; $ret['name'] = $this->name; - $ret['soa_edit'] = $this->soa_edit; - $ret['soa_edit_api'] = $this->soa_edit_api; + if (isset($this->soa_edit) && $this->soa_edit != "") { + $ret['soa_edit'] = $this->soa_edit; + } + if (isset($this->soa_edit_api) && $this->soa_edit_api != "") { + $ret['soa_edit_api'] = $this->soa_edit_api; + } if ($this->zone) { $ret['zone'] = $this->zone; return $ret; diff --git a/includes/misc.inc.php b/includes/misc.inc.php index d64cdd1..9046647 100644 --- a/includes/misc.inc.php +++ b/includes/misc.inc.php @@ -85,10 +85,12 @@ function string_ends_with($string, $suffix) } function get_db() { - global $authdb; + global $authdb, $db; - $db = new SQLite3($authdb, SQLITE3_OPEN_READWRITE); - $db->exec('PRAGMA foreign_keys = 1'); + if (!isset($db)) { + $db = new SQLite3($authdb, SQLITE3_OPEN_READWRITE); + $db->exec('PRAGMA foreign_keys = 1'); + } return $db; } @@ -130,7 +132,6 @@ function get_user_info($u) { $q->bindValue(1, $u); $result = $q->execute(); $userinfo = $result->fetchArray(SQLITE3_ASSOC); - $db->close(); return $userinfo; } @@ -145,7 +146,6 @@ function do_db_auth($u, $p) { $q->bindValue(1, $u); $result = $q->execute(); $userinfo = $result->fetchArray(SQLITE3_ASSOC); - $db->close(); if ($userinfo and $userinfo['password'] and (crypt($p, $userinfo['password']) === $userinfo['password'])) { return TRUE; @@ -169,7 +169,6 @@ function add_user($username, $isadmin = FALSE, $password = '') { $q->bindValue(2, $password, SQLITE3_TEXT); $q->bindValue(3, (int)(bool) $isadmin, SQLITE3_INTEGER); $ret = $q->execute(); - $db->close(); if ($isadmin) { writelog("Added user $username as admin."); @@ -207,7 +206,6 @@ function update_user($id, $isadmin, $password) { writelog("Updating settings for $username. Admin: ".(int)(bool)$isadmin); } $ret = $q->execute(); - $db->close(); return $ret; } @@ -225,7 +223,6 @@ function delete_user($id) { $q = $db->prepare('DELETE FROM users WHERE id = ?'); $q->bindValue(1, $id, SQLITE3_INTEGER); $ret = $q->execute(); - $db->close(); writelog("Deleted user " . $userinfo['emailaddress'] . "."); return $ret; @@ -265,6 +262,8 @@ function jtable_respond($records, $method = 'multiple', $msg = 'Undefined errorm $jTableResult['RecordCount'] = count($records); } + $db = get_db(); + $db->close(); header('Content-Type: application/json'); print json_encode($jTableResult); exit(0); @@ -314,7 +313,6 @@ function clearlogs() { $db = get_db(); $q = $db->query('DELETE FROM logs;'); - $db->close(); writelog("Logtable truncated."); } @@ -392,7 +390,6 @@ function writelog($line, $user=False) { $q->bindValue(':user', $user, SQLITE3_TEXT); $q->bindValue(':log', $line, SQLITE3_TEXT); $q->execute(); - $db->close(); } catch (Exception $e) { return jtable_respond(null, 'error', $e->getMessage()); } diff --git a/index.php b/index.php index 593ce29..e92e763 100644 --- a/index.php +++ b/index.php @@ -619,6 +619,8 @@ $(document).ready(function () { 'SRV': 'SRV', 'SSHFP': 'SSHFP', 'TLSA': 'TLSA', + 'DNAME': 'DNAME', + 'DS': 'DS' }; } return { @@ -626,6 +628,8 @@ $(document).ready(function () { 'AAAA': 'AAAA', 'CERT': 'CERT', 'CNAME': 'CNAME', + 'DNAME': 'DNAME', + 'DS': 'DS', 'LOC': 'LOC', 'MX': 'MX', 'NAPTR': 'NAPTR', @@ -1330,6 +1334,18 @@ $(document).ready(function () { entry: $('#searchlogs-entry').val() }); }); + + $('#AboutMe').hide(); + $('#aboutme').click(function () { + $('#MasterZones').hide(); + $('#SlaveZones').hide(); + $('#AboutMe').show(); + }); + $('#zoneadmin').click(function () { + $('#AboutMe').hide(); + $('#MasterZones').show(); + $('#SlaveZones').show(); + }); $('#MasterZones').jtable('load'); diff --git a/zones.php b/zones.php index b3618a0..45f650d 100644 --- a/zones.php +++ b/zones.php @@ -12,10 +12,12 @@ if (!is_csrf_safe()) { jtable_respond(null, 'error', "Authentication required"); } + +$quoteus = array('TXT', 'SPF'); + /* This function is taken from: http://pageconfig.com/post/how-to-validate-ascii-text-in-php and got fixed by #powerdns */ - function is_ascii($string) { return ( bool ) ! preg_match( '/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x80-\\xff]/' , $string ); } @@ -112,7 +114,6 @@ function add_db_zone($zonename, $accountname) { $q->bindValue(1, $zonename, SQLITE3_TEXT); $q->bindValue(2, $accountname, SQLITE3_TEXT); $q->execute(); - $db->close(); } function delete_db_zone($zonename) { @@ -123,7 +124,6 @@ function delete_db_zone($zonename) { $q = $db->prepare("DELETE FROM zones WHERE zone = ?"); $q->bindValue(1, $zonename, SQLITE3_TEXT); $q->execute(); - $db->close(); } function get_zone_account($zonename, $default) { @@ -135,7 +135,6 @@ function get_zone_account($zonename, $default) { $q->bindValue(1, $zonename, SQLITE3_TEXT); $result = $q->execute(); $zoneinfo = $result->fetchArray(SQLITE3_ASSOC); - $db->close(); if (isset($zoneinfo['emailaddress']) && $zoneinfo['emailaddress'] != null ) { return $zoneinfo['emailaddress']; } @@ -143,6 +142,16 @@ function get_zone_account($zonename, $default) { return $default; } +function quote_content($content) { + # empty TXT records are ok, otherwise require surrounding quotes: "..." + if (strlen($content) == 1 || substr($content, 0, 1) !== '"' || substr($content, -1) !== '"') { + # fix quoting: first escape all \, then all ", then surround with quotes. + $content = '"'.str_replace('"', '\\"', str_replace('\\', '\\\\', $content)).'"'; + } + + return $content; +} + function check_account($zone) { return is_adminuser() or ($zone->account === get_sess_user()); } @@ -165,7 +174,9 @@ case "listslaves": foreach ($api->listzones($q) as $sresult) { $zone = new Zone(); $zone->parse($sresult); - $zone->setAccount(get_zone_account($zone->name, 'admin')); + if ($zone->account == '') { + $zone->setAccount(get_zone_account($zone->name, 'admin')); + } if (!check_account($zone)) continue; @@ -273,7 +284,7 @@ case "create": $zone->importData($_POST['zone']); } if (isset($defaults['soa_edit_api'])) { - $zone->setSoaEditApi($defaults['soa_edit_api']); + $zone->setSoaEditApi($defaults['soa_edit_api'], True); } if (isset($defaults['soa_edit'])) { $zone->setSoaEdit($defaults['soa_edit']); @@ -319,7 +330,8 @@ case "create": $api->savezone($zone->export()); foreach ($template['records'] as $record) { - $zone->addRecord($record['name'], $record['type'], $record['content']); + $name = $record['name'] != '' ? join(Array($record['name'],'.',$zonename)) : $zonename; + $zone->addRecord($name, $record['type'], $record['content']); } break; @@ -334,6 +346,8 @@ case "create": case "update": $zone = new Zone(); $zone->parse($api->loadzone($_POST['id'])); + if ($zone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$zone->name); $zoneaccount = isset($_POST['account']) ? $_POST['account'] : $zone->account; if ($zone->account !== $zoneaccount) { @@ -360,6 +374,8 @@ case "update": case "createrecord": $zone = new Zone(); $zone->parse($api->loadzone($_GET['zoneid'])); + if ($zone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$zone->name); $name = isset($_POST['name']) ? $_POST['name'] : ''; $type = $_POST['type']; @@ -369,12 +385,13 @@ case "createrecord": $name = $zone->name; } elseif (string_ends_with($name, '.')) { # "absolute" name, shouldn't append zone[name] - but check. - $name = substr($name, 0, -1); if (!string_ends_with($name, $zone->name)) { jtable_respond(null, 'error', "Name $name not in zone ".$zone->name); } - } else if (!string_ends_with($name, $zone->name)) { + } else if (!string_ends_with($name.'.', $zone->name)) { $name = $name . '.' . $zone->name; + } else { + $name = $name.'.'; } if (!_valid_label($name)) { @@ -387,6 +404,10 @@ case "createrecord": jtable_respond(null, 'error', "Please only use ASCII-characters in your fields"); } + if (array_search($type, $quoteus) !== FALSE) { + $content = quote_content($content); + } + $record = $zone->addRecord($name, $type, $content, $_POST['disabled'], $_POST['ttl'], $_POST['setptr']); $api->savezone($zone->export()); @@ -397,16 +418,24 @@ case "createrecord": case "editrecord": $zone = new Zone(); $zone->parse($api->loadzone($_GET['zoneid'])); + if ($zone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$zone->name); $old_record = decode_record_id(isset($_POST['id']) ? $_POST['id'] : ''); $rrset = $zone->getRRSet($old_record['name'], $old_record['type']); $rrset->deleteRecord($old_record['content']); - $zone->addRecord($_POST['name'], $_POST['type'], $_POST['content'], $_POST['disabled'], $_POST['ttl'], $_POST['setptr']); + + $content = $_POST['content']; + if (array_search($type, $quoteus) !== FALSE) { + $content = quote_content($content); + } + + $zone->addRecord($_POST['name'], $_POST['type'], $content, $_POST['disabled'], $_POST['ttl'], $_POST['setptr']); $api->savezone($zone->export()); - $record = $zone->getRecord($_POST['name'], $_POST['type'], $_POST['content']); + $record = $zone->getRecord($_POST['name'], $_POST['type'], $content); writelog("Updated record ".$_POST['id']." to ".$record['id']); jtable_respond($record, 'single'); break; @@ -414,6 +443,8 @@ case "editrecord": case "deleterecord": $zone = new Zone(); $zone->parse($api->loadzone($_GET['zoneid'])); + if ($zone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$zone->name); $old_record = decode_record_id(isset($_POST['id']) ? $_POST['id'] : ''); $rrset = $zone->getRRSet($old_record['name'], $old_record['type']); @@ -444,6 +475,8 @@ case "clone": $srczone = new Zone(); $srczone->parse($api->loadzone($src)); + if ($srczone->setSoaEditApi($defaults['soa_edit_api']) != False) + writelog("Set SOA-EDIT-API to ".$defaults['soa_edit_api']." for ",$srczone->name); $srczone->setId(''); $srczone->setName($name); @@ -496,6 +529,7 @@ case "getformnameservers": break; case "formzonelist": $zones = $api->listzones(); + usort($zones, "zone_compare"); $ret = array(); foreach ($zones as $zone) { if ($zone['kind'] == 'Slave')