diff --git a/api/edit-master.php b/api/edit-master.php
index 2aa58ec..6859d4a 100644
--- a/api/edit-master.php
+++ b/api/edit-master.php
@@ -20,6 +20,7 @@ require_once '../config/config-default.php';
require_once '../lib/database.php';
require_once '../lib/session.php';
require_once '../lib/soa-mail.php';
+require_once '../lib/update-serial.php';
$input = json_decode(file_get_contents('php://input'));
@@ -151,4 +152,130 @@ if(isset($input->action) && $input->action == "getSoa") {
}
-echo json_encode($retval);
+//Action for getting SOA
+if(isset($input->action) && $input->action == "getSerial") {
+ $domainId = (int)$input->domain;
+
+ $stmt = $db->prepare("SELECT content FROM records WHERE type='SOA' AND domain_id=?");
+ $stmt->bind_param("i", $domainId);
+ $stmt->execute();
+
+ $stmt->bind_result($content);
+ $stmt->fetch();
+
+ $content = explode(" ", $content);
+
+ $retval = Array();
+
+ $retval['serial'] = $content[2];
+}
+
+//Action for saving SOA
+if(isset($input->action) && $input->action == "saveSoa") {
+ $domainId = (int)$input->domain;
+
+ $db->autocommit(false);
+ $db->begin_transaction();
+
+ $stmt = $db->prepare("SELECT content FROM records WHERE type='SOA' AND domain_id=?");
+ $stmt->bind_param("i", $domainId);
+ $stmt->execute();
+ $stmt->bind_result($content);
+ $stmt->fetch();
+ $stmt->close();
+
+ $content = explode(" ", $content);
+ $serial = $content[2];
+
+ $newsoa = $input->primary . " ";
+ $newsoa .= mail_to_soa($input->email) . " ";
+ $newsoa .= $serial . " ";
+ $newsoa .= $input->refresh . " ";
+ $newsoa .= $input->retry . " ";
+ $newsoa .= $input->expire . " ";
+ $newsoa .= $input->ttl;
+
+ $stmt = $db->prepare("UPDATE records SET content=? WHERE type='SOA' AND domain_id=?");
+ $stmt->bind_param("si", $newsoa, $domainId);
+ $stmt->execute();
+
+ $db->commit();
+
+ $retval = Array();
+
+ update_serial($db, $domainId);
+}
+
+//Action for saving Record
+if(isset($input->action) && $input->action == "saveRecord") {
+ $domainId = $input->domain;
+
+ $stmt = $db->prepare("UPDATE records SET name=?,type=?,content=?,ttl=?,prio=? WHERE id=? AND domain_id=?");
+ $stmt->bind_param("sssiiii",
+ $input->name, $input->type,
+ $input->content, $input->ttl,
+ $input->prio,
+ $input->id, $domainId
+ );
+ $stmt->execute();
+ update_serial($db, $domainId);
+}
+
+//Action for adding Record
+if(isset($input->action) && $input->action == "addRecord") {
+ $domainId = $input->domain;
+
+ $stmt = $db->prepare("INSERT INTO records (domain_id, name, type, content, prio, ttl) VALUES (?,?,?,?,?,?)");
+ $stmt->bind_param("isssii",
+ $domainId, $input->name,
+ $input->type, $input->content,
+ $input->prio, $input->ttl
+ );
+ $stmt->execute();
+ $stmt->close();
+
+ $stmt = $db->prepare("SELECT LAST_INSERT_ID()");
+ $stmt->execute();
+ $stmt->bind_result($newId);
+ $stmt->fetch();
+ $stmt->close();
+
+ $retval = Array();
+ $retval['newId'] = $newId;
+
+ update_serial($db, $domainId);
+}
+
+//Action for removing Record
+if(isset($input->action) && $input->action == "removeRecord") {
+ $domainId = $input->domain;
+ $recordId = $input->id;
+
+ $stmt = $db->prepare("DELETE FROM records WHERE id=? AND domain_id=?");
+ $stmt->bind_param("ii", $recordId, $domainId);
+ $stmt->execute();
+ $stmt->close();
+
+ update_serial($db, $domainId);
+}
+
+//Action for getting domain name
+if(isset($input->action) && $input->action == "getDomainName") {
+ $domainId = $input->domain;
+
+ $stmt = $db->prepare("SELECT name FROM domains WHERE id=?");
+ $stmt->bind_param("i", $domainId);
+ $stmt->execute();
+ $stmt->bind_result($domainName);
+ $stmt->fetch();
+ $stmt->close();
+
+ $retval = Array();
+ $retval['name'] = $domainName;
+}
+
+if (isset($retval)) {
+ echo json_encode($retval);
+} else {
+ echo "{}";
+}
diff --git a/edit-master.php b/edit-master.php
index efab7f1..f5a86b0 100644
--- a/edit-master.php
+++ b/edit-master.php
@@ -51,7 +51,7 @@ limitations under the License.
diff --git a/js/edit-master.js b/js/edit-master.js
index 99fda86..da0d661 100644
--- a/js/edit-master.js
+++ b/js/edit-master.js
@@ -17,7 +17,18 @@
var sort = {
field: "",
order: 1
-}
+};
+
+var domainName = "";
+
+var recordTypes = [
+ "A","AAAA","AFSDB","CERT","CNAME","DHCID",
+ "DLV","DNSKEY","DS","EUI48","EUI64","HINFO",
+ "IPSECKEY","KEY","KX","LOC","MINFO","MR",
+ "MX","NAPTR","NS","NSEC","NSEC3","NSEC3PARAM",
+ "OPT","PTR","RKEY","RP","RRSIG","SOA","SPF",
+ "SRV","SSHFP","TLSA","TSIG","TXT","WKS"
+];
$(document).ready(function() {
@@ -42,7 +53,12 @@ $(document).ready(function() {
});
$('#searchType').select2({
- placeholder: "Filter..."
+ placeholder: "Filter...",
+ data: recordTypes
+ });
+
+ $('#addType').select2({
+ data: recordTypes
});
$('#table-records>thead>tr>td span.glyphicon').click(function() {
@@ -70,10 +86,13 @@ $(document).ready(function() {
$('#searchType').change(function() {
requestRecordData();
});
-
+
+ $('#addButton').click(addRecord);
+
requestRecordData();
requestSoaData();
-
+ requestSerial();
+ requestDomainName();
});
function validateSoaData() {
@@ -101,10 +120,13 @@ function recreateTable(data) {
.append('' + item.content + ' | ')
.append('' + item.priority + ' | ')
.append('' + item.ttl + ' | ')
- .append(' | ')
- .append(' | ');
+ .append(' | ')
+ .append(' | ');
});
+
+ $('#table-records>tbody>tr>td>span.glyphicon-trash').click(trashClicked);
+ $('#table-records>tbody>tr>td>span.glyphicon-pencil').click(editClicked);
}
function requestRecordData() {
@@ -158,6 +180,22 @@ function requestSoaData() {
$('#soa-retry').val(data.retry);
$('#soa-expire').val(data.expire);
$('#soa-ttl').val(data.ttl);
+ },
+ "json"
+ );
+}
+
+function requestSerial() {
+ var data = {
+ action: "getSerial"
+ };
+
+ data.domain = location.hash.substring(1);
+
+ $.post(
+ "api/edit-master.php",
+ JSON.stringify(data),
+ function(data) {
$('#soa-serial').val(data.serial);
},
"json"
@@ -165,5 +203,184 @@ function requestSoaData() {
}
function saveSoaData() {
+ var data = {
+ action: "saveSoa"
+ };
+ data.domain = location.hash.substring(1);
+
+ data.primary = $('#soa-primary').val();
+ data.email = $('#soa-mail').val();
+ data.refresh = $('#soa-refresh').val();
+ data.retry = $('#soa-retry').val();
+ data.expire = $('#soa-expire').val();
+ data.ttl = $('#soa-ttl').val();
+
+ $.post(
+ "api/edit-master.php",
+ JSON.stringify(data),
+ function() {
+ requestSerial();
+ },
+ "json"
+ );
+}
+
+function editClicked() {
+ var tableCells = $(this).parent().parent().children('td');
+ var tableRow = $(this).parent().parent();
+
+ var valueName = tableCells.eq(1).text();
+ tableCells.eq(1).empty();
+ $('').appendTo(tableCells.eq(1)).val(valueName);
+
+ var valueType = tableCells.eq(2).text();
+ tableCells.eq(2).empty();
+ $('').appendTo(tableCells.eq(2)).select2({
+ data: recordTypes
+ }).val(valueType).trigger("change");
+
+ var valueContent = tableCells.eq(3).text();
+ tableCells.eq(3).empty();
+ $('').appendTo(tableCells.eq(3)).val(valueContent);
+
+ var valuePrio = tableCells.eq(4).text();
+ tableCells.eq(4).empty();
+ $('').appendTo(tableCells.eq(4)).val(valuePrio);
+
+ var valueTtl = tableCells.eq(5).text();
+ tableCells.eq(5).empty();
+ $('').appendTo(tableCells.eq(5)).val(valueTtl);
+
+ tableCells.eq(6).remove();
+ tableCells.eq(7).remove();
+
+ $(tableRow).append(' | ');
+
+ $(tableRow).find('button').click(saveRecord);
+
+ enableFilter(false);
+}
+
+function saveRecord() {
+
+ var tableRow = $(this).parent().parent();
+
+ var data = {
+ id: tableRow.children('td').eq(0).text(),
+ name: tableRow.children('td').eq(1).children('input').val(),
+ type: tableRow.children('td').eq(2).children('select').val(),
+ content: tableRow.children('td').eq(3).children('input').val(),
+ prio: tableRow.children('td').eq(4).children('input').val(),
+ ttl: tableRow.children('td').eq(5).children('input').val(),
+ action: "saveRecord",
+ domain: location.hash.substring(1)
+ };
+
+ tableRow.children('td').eq(0).empty().text(data.id);
+ tableRow.children('td').eq(1).empty().text(data.name);
+ tableRow.children('td').eq(2).empty().text(data.type);
+ tableRow.children('td').eq(3).empty().text(data.content);
+ tableRow.children('td').eq(4).empty().text(data.prio);
+ tableRow.children('td').eq(5).empty().text(data.ttl);
+
+ tableRow.children('td').eq(6).remove();
+
+ tableRow.append(' | ')
+ .append(' | ');
+ tableRow.find('span.glyphicon-trash').click(trashClicked);
+ tableRow.find('span.glyphicon-pencil').click(editClicked);
+
+ enableFilter(true);
+
+ $.post(
+ "api/edit-master.php",
+ JSON.stringify(data),
+ function() {
+ requestSerial();
+ },
+ "json"
+ );
+}
+
+function addRecord() {
+ var data = {
+ name: $('#addName').val(),
+ type: $('#addType').val(),
+ content: $('#addContent').val(),
+ prio: $('#addPrio').val(),
+ ttl: $('#addTtl').val(),
+ action: "addRecord",
+ domain: location.hash.substring(1)
+ };
+
+ $.post(
+ "api/edit-master.php",
+ JSON.stringify(data),
+ function(dataRecv) {
+ $('
').appendTo('#table-records>tbody')
+ .append('' + dataRecv.newId + ' | ')
+ .append('' + data.name + ' | ')
+ .append('' + data.type + ' | ')
+ .append('' + data.content + ' | ')
+ .append('' + data.prio + ' | ')
+ .append('' + data.ttl + ' | ')
+ .append(' | ')
+ .append(' | ')
+ .find('span.glyphicon-trash').click(trashClicked)
+ .find('span.glyphicon-pencil').click(editClicked);
+
+ requestSerial();
+ },
+ "json"
+ );
+}
+
+function trashClicked() {
+ var data = {
+ id: $(this).parent().parent().children().eq(0).text(),
+ domain: location.hash.substring(1),
+ action: "removeRecord"
+ };
+
+ var lineAffected = $(this).parent().parent();
+
+ $.post(
+ "api/edit-master.php",
+ JSON.stringify(data),
+ function() {
+ lineAffected.remove();
+ requestSerial();
+ },
+ "json"
+ );
+}
+
+function requestDomainName() {
+ var data = {
+ action: "getDomainName",
+ domain: location.hash.substring(1)
+ };
+
+ $.post(
+ "api/edit-master.php",
+ JSON.stringify(data),
+ function(data) {
+ $('#domain-name').text(data.name);
+ domainName = data.name;
+ },
+ "json"
+ );
+}
+
+function enableFilter(enable) {
+ if(enable) {
+ $('#searchName').prop("disabled", false);
+ $('#searchType').prop("disabled", false);
+ $('#searchContent').prop("disabled", false);
+ } else {
+ $('#searchName').prop("disabled", true);
+ $('#searchType').prop("disabled", true);
+ $('#searchContent').prop("disabled", true);
+ }
}
\ No newline at end of file
diff --git a/lib/update-serial.php b/lib/update-serial.php
new file mode 100644
index 0000000..f1ee3fe
--- /dev/null
+++ b/lib/update-serial.php
@@ -0,0 +1,59 @@
+.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function update_serial($db, $domainId) {
+
+ $db->autocommit(false);
+ $db->begin_transaction();
+
+ $stmt = $db->prepare("SELECT content FROM records WHERE type='SOA' AND domain_id=?");
+ $stmt->bind_param("i", $domainId);
+ $stmt->execute();
+ $stmt->bind_result($content);
+ $stmt->fetch();
+ $stmt->close();
+
+ $content = explode(" ", $content);
+
+ $serial = $content[2];
+
+ $currentSerialDate = (int)($serial / 100);
+ $currentSerialSequence = $serial % 100;
+
+ $currentDate = (int)date("Ymd");
+
+ if($currentDate != $currentSerialDate) {
+ $newSerial = $currentDate . "00";
+ } else {
+ $newSerialSequence = ($currentSerialSequence+1)%100 . "";
+ $newSerialSequence = str_pad($newSerialSequence, 2, "0", STR_PAD_LEFT);
+ $newSerial = $currentDate . "" . $newSerialSequence;
+ }
+
+ $content[2] = $newSerial;
+
+
+ $newsoa = implode(" ", $content);
+
+ $stmt = $db->prepare("UPDATE records SET content=? WHERE type='SOA' AND domain_id=?");
+ $stmt->bind_param("si", $newsoa, $domainId);
+ $stmt->execute();
+
+ $db->commit();
+
+}
\ No newline at end of file