sddns/include/zone.php
2011-08-19 20:55:53 +02:00

190 lines
4.9 KiB
PHP
Executable file

<?php
class Zone extends NameServer implements Object {
public $name;
private $key;
function __construct($nserver, $name, $key, $nsport = 53) {
parent::__construct($nserver, $nsport);
$this->name = $name;
$this->key = $key;
}
protected function initialize() {
parent::initialize();
$this->queueCommand('zone ' . $this->name);
$this->queueCommand('key ' . $this->key['name'] . ' ' . $this->key['hmac']);
}
/*
* Maintenance
*/
function cleanup(Database $db) {
$config = Registry::get('config');
$output = Registry::get('output');
// expired records & records without host
$sql = 'DELETE r FROM ' . $config['db']['tbl']['records'] . ' AS r
LEFT JOIN ' . $config['db']['tbl']['hosts'] . ' AS h
ON h.id = r.host_id
WHERE
((r.last_accessed + INTERVAL r.lifetime SECOND) < NOW() &&
h.zone = \'' . $db->escape($this->name) . '\') || h.id IS NULL';
$db->execute($sql);
if ($db->affectedRows() > 0)
$output->add('records deleted from db', 'success', $db->affectedRows(), $this);
// expired urls & uris without host
$sql = 'DELETE u FROM ' . $config['db']['tbl']['uris'] . ' AS u
LEFT JOIN ' . $config['db']['tbl']['hosts'] . ' AS h
ON h.id = u.host_id
WHERE
((u.last_accessed + INTERVAL u.lifetime SECOND) < NOW() &&
h.zone = \'' . $db->escape($this->name) . '\') || h.id IS NULL';
$db->execute($sql);
if ($db->affectedRows() > 0)
$output->add('urls deleted from db', 'success', $db->affectedRows(), $this);
// hosts without records or url
$sql = 'DELETE h
FROM ' . $config['db']['tbl']['hosts'] . ' AS h
LEFT JOIN ' . $config['db']['tbl']['records'] . ' AS r
ON h.id = r.host_id
LEFT JOIN ' . $config['db']['tbl']['uris'] . ' AS u
ON h.id = u.host_id
WHERE
(r.id IS NULL && u.id IS NULL) &&
h.zone = \'' . $db->escape($this->name) . '\'';
$db->execute($sql);
if ($db->affectedRows() > 0)
$output->add('hosts deleted from db', 'success', $db->affectedRows(), $this);
}
public function sync(Database $db) {
$output = Registry::get('output');
$nsRecords = $this->getRecordsFromNS();
$dbRecords = $this->getRecordsFromDB($db);
$delete = array_diff($nsRecords, $dbRecords);
$add = array_diff($dbRecords, $nsRecords);
foreach ($add as $record) {
$this->add($record);
$output->add('record added to ns', 'success', $record);
}
foreach ($delete as $record) {
$this->delete($record);
$output->add('record deleted from ns', 'success', $record);
}
}
public function add(Record $record) {
$config = Registry::get('config');
if ($record->host->zone->name != $this->name) {
throw new NameServerException('zone mismatch: trying to add record "' . $record . '" to zone "' . $this . '"');
}
parent::add($record);
$nsresult = $this->sendQueue();
if($nsresult['code'] != 0) {
throw new NameServerException('error during nameserver update: ' . $nsresult['stderr']);
}
return true;
}
public function delete(Record $record) {
$config = Registry::get('config');
if ($record->host->zone->name != $this->name) {
throw new NameServerException('zone mismatch: trying to delete record ' . $record . ' from zone ' . $this);
}
parent::delete($record);
$nsresult = $this->sendQueue();
if($nsresult['code'] != 0) {
throw new NameServerException('error during nameserver update: ' . $nsresult['stderr']);
}
return true;
}
/*
* Getter
*/
public function getRecordsFromNS() {
$config = Registry::get('config');
$output = Registry::get('output');
$records = array();
foreach (parent::query($this->name, 'AXFR') as $result) {
if (in_array($result[3], $config['sddns']['types']) && strlen($result[0]) > strlen($this->name) + 1) {
$hostname = substr($result[0], 0, -(strlen($this->name) + 2));
switch ($result[3]) {
case 'NS':
case 'MX':
case 'CNAME':
$rdata = substr($result[4], 0, -1);
break;
case 'TXT':
$rdata = trim($result[4], '"');
break;
default:
$rdata = $result[4];
}
try {
$host = new Host($hostname, $this);
$records[] = new Record($host, (int) $result[1], $result[2], $result[3], $rdata);
} catch (UserException $e) {
$output->add('error during parsing', 'error', $e);
}
}
}
return $records;
}
public function getRecordsFromDB(Database $db) {
return DBRecord::get($db, array('zone' => $this));
}
public function getUrisFromDB(Database $db) {
return DBUri::get($db, array('zone' => $this));
}
public function getHostsFromDB(Database $db) {
return DBHost::get($db, array('zone' => $this));
}
/*
* Output
*/
public function __toString() {
return parent::__toString() . '/' . $this->name;
}
public function toXml(DOMDocument $doc) {
$xmlZone = parent::toXml($doc, 'zone');
$xmlZone->appendChild($doc->createElement('zone', $this->name));
return $xmlZone;
}
public function toHtml() {
return $this;
}
}