Skip to content

Commit

Permalink
Rewrite of SOA update function. Now honors a serial of "0" (as this h…
Browse files Browse the repository at this point in the history
…as special meaning for Powerdns) and simplified code. Fixed a bug in edit.php which caused serial not to be changed when records were changed. User is now forced to edit SOA record explicitly. Closes poweradmin#66.
  • Loading branch information
rejozenger committed Dec 27, 2008
1 parent 89fa21b commit a48b9f6
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 88 deletions.
49 changes: 30 additions & 19 deletions edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,12 @@
echo " <th>" . _('TTL') . "</th>\n";
echo " </tr>\n";
foreach ($records as $r) {
echo " <input type=\"hidden\" name=\"record[" . $r['id'] . "][rid]\" value=\"" . $r['id'] . "\">\n";
echo " <input type=\"hidden\" name=\"record[" . $r['id'] . "][zid]\" value=\"" . $zone_id . "\">\n";
if ($r['type'] != "SOA") {
echo " <input type=\"hidden\" name=\"record[" . $r['id'] . "][rid]\" value=\"" . $r['id'] . "\">\n";
echo " <input type=\"hidden\" name=\"record[" . $r['id'] . "][zid]\" value=\"" . $zone_id . "\">\n";
}
echo " <tr>\n";

if ( $domain_type == "SLAVE" || $perm_content_edit == "none" || $perm_content_edit == "own" && $user_is_zone_owner == "0" ) {
echo " <td class=\"n\">&nbsp;</td>\n";
} else {
Expand All @@ -113,26 +116,34 @@
<img src=\"images/delete.gif\" ALT=\"[ " . _('Delete record') . " ]\" BORDER=\"0\"></a>\n";
echo " </td>\n";
}
echo " <td class=\"u\"><input class=\"wide\" name=\"record[" . $r['id'] . "][name]\" value=\"" . $r['name'] . "\"></td>\n";
echo " <td class=\"u\">\n";
echo " <select name=\"record[" . $r['id'] . "][type]\">\n";
foreach (get_record_types() as $type_available) {
if ($type_available == $r['type']) {
$add = " SELECTED";
if ($r['type'] == "SOA") {
echo " <td class=\"n\">" . $r['name'] . "</td>\n";
echo " <td class=\"n\">" . $r['type'] . "</td>\n";
echo " <td class=\"n\">" . $r['content'] . "</td>\n";
echo " <td class=\"n\">&nbsp;</td>\n";
echo " <td class=\"n\">" . $r['ttl'] . "</td>\n";
} else {
echo " <td class=\"u\"><input class=\"wide\" name=\"record[" . $r['id'] . "][name]\" value=\"" . $r['name'] . "\"></td>\n";
echo " <td class=\"u\">\n";
echo " <select name=\"record[" . $r['id'] . "][type]\">\n";
foreach (get_record_types() as $type_available) {
if ($type_available == $r['type']) {
$add = " SELECTED";
} else {
$add = "";
}
echo " <option" . $add . " value=\"" . $type_available . "\" >" . $type_available . "</option>\n";
}
echo " </select>\n";
echo " </td>\n";
echo " <td class=\"u\"><input class=\"wide\" name=\"record[" . $r['id'] . "][content]\" value=\"" . $r['content'] . "\"></td>\n";
if ($r['type'] == "MX") {
echo " <td class=\"u\"><input name=\"record[" . $r['id'] . "][prio]\" value=\"" . $r['prio'] . "\"></td>\n";
} else {
$add = "";
echo " <td class=\"n\">&nbsp;</td>\n";
}
echo " <option" . $add . " value=\"" . $type_available . "\" >" . $type_available . "</option>\n";
}
echo " </select>\n";
echo " </td>\n";
echo " <td class=\"u\"><input class=\"wide\" name=\"record[" . $r['id'] . "][content]\" value=\"" . $r['content'] . "\"></td>\n";
if ($r['type'] == "MX") {
echo " <td class=\"u\"><input name=\"record[" . $r['id'] . "][prio]\" value=\"" . $r['prio'] . "\"></td>\n";
} else {
echo " <td class=\"n\">&nbsp;</td>\n";
echo " <td class=\"u\"><input name=\"record[" . $r['id'] . "][ttl]\" value=\"" . $r['ttl'] . "\"></td>\n";
}
echo " <td class=\"u\"><input name=\"record[" . $r['id'] . "][ttl]\" value=\"" . $r['ttl'] . "\"></td>\n";
echo " </tr>\n";
}
echo " </table>\n";
Expand Down
131 changes: 62 additions & 69 deletions inc/record.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,56 +42,63 @@ function count_zone_records($zone_id) {
return $record_count;
}

function update_soa_serial($domain_id)
{
global $db;
function update_soa_serial($did) {

$sqlq = "SELECT notified_serial FROM domains WHERE id = ".$db->quote($domain_id, 'integer');
global $db;
$sqlq = "SELECT notified_serial FROM domains WHERE id = ".$db->quote($did, 'integer');
$notified_serial = $db->queryOne($sqlq);

$sqlq = "SELECT content FROM records WHERE type = ".$db->quote('SOA', 'text')." AND domain_id = ".$db->quote($domain_id, 'integer');
$content = $db->queryOne($sqlq);
$sqlq = "SELECT content FROM records WHERE type = ".$db->quote('SOA', 'text')." AND domain_id = ".$db->quote($did, 'integer');
$result = $db->queryOne($sqlq);
$need_to_update = false;

// Getting the serial field.
$soa = explode(" ", $content);
// Split content of current SOA record into an array.
$soa = explode(" ", $result);

if(empty($notified_serial)) {
// Ok native replication, so we have to update.
$need_to_update = true;
} elseif($notified_serial >= $soa[2]) {
$need_to_update = true;
} elseif(strlen($soa[2]) != 10) {
$need_to_update = true;
// Check if we have to update the serial field.
//
// The serial should be updated, unless:
// - the serial is set to "0", see /Documentation/DNS-SOA#PowerDNSspecifics on
// the Poweradmin website
// - the serial is set to YYYYMMDD99, it's RFC 1912 style already and has
// reached it limit of revisions for today

if ($soa[2] == "0") {
return true;
} elseif ($soa[2] == date('Ymd') . "99") {
return true;
} else {
$need_to_update = false;
}

if($need_to_update) {
// Ok so we have to update it seems.
$current_serial = $soa[2];
$new_serial = date('Ymd'); // we will add revision number later

if(strncmp($new_serial, $current_serial, 8) === 0) {
$revision_number = (int) substr($current_serial, -2);
if ($revision_number == 99) return false; // ok, we cannot update anymore tonight
++$revision_number;
// here it is ... same date, new revision
$new_serial .= str_pad($revision_number, 2, "0", STR_PAD_LEFT);
$today = date('Ymd');

// Determine revision.
if (strncmp($today, $soa[2], 8) === 0) {
// Current serial starts with date of today, so we need to update
// the revision only. To do so, determine current revision first,
// then update counter.
$revision = (int) substr($soa[2], -2);
++$revision;
} else {
/*
* Current serial is not RFC1912 compilant, so let's make a new one
*/
$new_serial .= '00';
// Current serial did not start of today, so it's either an older
// serial or a serial that does not adhere the recommended syntax
// of RFC-1912. In either way, set a fresh serial
$revision = "00";
}
$soa[2] = $new_serial; // change serial in SOA array
$new_soa = "";
// build new soa and update SQL after that

// TODO padding if revision < 10
$serial = $today . $revision;

// Change serial in SOA array.
$soa[2] = $serial;

// Build new SOA record content and update the database.
$content = "";
for ($i = 0; $i < count($soa); $i++) {
$new_soa .= $soa[$i] . " ";
$content .= $soa[$i] . " ";
}
$sqlq = "UPDATE records SET content = ".$db->quote($new_soa, 'text')." WHERE domain_id = ".$db->quote($domain_id, 'integer')." AND type = ".$db->quote('SOA', 'text');
$db->Query($sqlq);
// TODO Query not executed?
$sqlq = "UPDATE records SET content = ".$db->quote($content, 'text')." WHERE domain_id = ".$db->quote($did, 'integer')." AND type = ".$db->quote('SOA', 'text');
$response = $db->query($sqlq);
if (PEAR::isError($response)) { error($response->getMessage()); return false; }
return true;
}
}
Expand All @@ -102,7 +109,7 @@ function update_soa_serial($domain_id)
* return values: true if succesful.
*/
function edit_record($record) {

if (verify_permission('zone_content_edit_others')) { $perm_content_edit = "all" ; }
elseif (verify_permission('zone_content_edit_own')) { $perm_content_edit = "own" ; }
else { $perm_content_edit = "none" ; }
Expand All @@ -114,38 +121,24 @@ function edit_record($record) {
error(ERR_PERM_EDIT_RECORD);
return false;
} else {
if($record['content'] == "") {
error(ERR_DNS_CONTENT);
return false;
}
global $db;
// TODO: no need to check for numeric-ness of zone id if we check with validate_input as well?
if (is_numeric($record['zid'])) {
if (validate_input($record['zid'], $record['type'], $record['content'], $record['name'], $record['prio'], $record['ttl'])) {
$query = "UPDATE records
SET name=".$db->quote($record['name'], 'text').",
type=".$db->quote($record['type'], 'text').",
content=" . $db->quote($record['content'], 'text') . ",
ttl=".$db->quote($record['ttl'], 'integer').",
prio=".$db->quote($record['prio'], 'integer').",
change_date=".$db->quote(time(), 'integer')."
WHERE id=".$db->quote($record['rid'], 'integer');
$result = $db->Query($query);
if (PEAR::isError($result)) {
error($result->getMessage());
return false;
} elseif ($record['type'] != 'SOA') {
update_soa_serial($record['zid']);
}
return true;
if (validate_input($record['zid'], $record['type'], $record['content'], $record['name'], $record['prio'], $record['ttl'])) {
$query = "UPDATE records
SET name=".$db->quote($record['name'], 'text').",
type=".$db->quote($record['type'], 'text').",
content=" . $db->quote($record['content'], 'text') . ",
ttl=".$db->quote($record['ttl'], 'integer').",
prio=".$db->quote($record['prio'], 'integer').",
change_date=".$db->quote(time(), 'integer')."
WHERE id=".$db->quote($record['rid'], 'integer');
$result = $db->query($query);
if (PEAR::isError($result)) { error($result->getMessage()); return false; }
if ($record['type'] != 'SOA') {
update_soa_serial($record['zid']);
}
return false;
}
else
{
// TODO change to error style as above (returning directly)
error(sprintf(ERR_INV_ARGC, "edit_record", "no zoneid given"));
return true;
}
return false;
}
return true;
}
Expand Down

0 comments on commit a48b9f6

Please sign in to comment.