mirror of
https://github.com/tuxis-ie/nsedit.git
synced 2025-04-19 20:09:14 +03:00
Compare commits
125 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7a18c00a24 | ||
![]() |
2ea8bff800 | ||
![]() |
12d3d33c36 | ||
![]() |
6c565719d9 | ||
![]() |
fe4120e2a7 | ||
![]() |
8e1d0035d3 | ||
![]() |
a3ba9ed45e | ||
![]() |
3b69fcf770 | ||
![]() |
65d58cfd92 | ||
![]() |
c8f28c5c3e | ||
![]() |
39050cd015 | ||
![]() |
e8d028ba75 | ||
![]() |
a4aa3c35cf | ||
![]() |
e5a121f24b | ||
![]() |
76d70251bb | ||
![]() |
b7ef64db18 | ||
![]() |
758a021ca2 | ||
![]() |
cae4e4ff93 | ||
![]() |
7c50964633 | ||
![]() |
d59da92f37 | ||
![]() |
607ecbd9f2 | ||
![]() |
c327e23859 | ||
![]() |
e38fa1e120 | ||
![]() |
b8e3261180 | ||
![]() |
947ec4a67d | ||
![]() |
d414f239a8 | ||
![]() |
8efcfbd597 | ||
![]() |
5c6c9e1847 | ||
![]() |
888e7bad42 | ||
![]() |
82db64595c | ||
![]() |
6ba23a85b8 | ||
![]() |
059c679193 | ||
![]() |
8586816c47 | ||
![]() |
de278c9ad7 | ||
![]() |
371eb41787 | ||
![]() |
c63dbba617 | ||
![]() |
9407c92a6a | ||
![]() |
23b9fe2c54 | ||
![]() |
523fc1849d | ||
![]() |
3448ccf653 | ||
![]() |
e80aa0dca7 | ||
![]() |
92290bdf05 | ||
![]() |
3facd3271f | ||
![]() |
be647cc26a | ||
![]() |
bf513b9ffd | ||
![]() |
880508f585 | ||
![]() |
39cf7138ef | ||
![]() |
e403e396bc | ||
![]() |
96c67a8e8f | ||
![]() |
805176648d | ||
![]() |
ebd12ebeb2 | ||
![]() |
1dedc3ae3f | ||
![]() |
77d7c50110 | ||
![]() |
635441dbe0 | ||
![]() |
ed27b5e7d1 | ||
![]() |
a2d7c21636 | ||
![]() |
4f013d4081 | ||
![]() |
d44b1a011f | ||
![]() |
6dc6df497e | ||
![]() |
cb234599b7 | ||
![]() |
03d9d88026 | ||
![]() |
1dfd47ae70 | ||
![]() |
c1c680217d | ||
![]() |
374e03aa43 | ||
![]() |
877d433b92 | ||
![]() |
ac5304badb | ||
![]() |
fd2a7cb7a5 | ||
![]() |
c3bd9da355 | ||
![]() |
0befe9e5ab | ||
![]() |
0c1183e716 | ||
![]() |
4b060c6430 | ||
![]() |
18fa97373e | ||
![]() |
1f2225cf6d | ||
![]() |
382ca51db1 | ||
![]() |
6be5f2f29c | ||
![]() |
f67fa04d85 | ||
![]() |
9d27a140d7 | ||
![]() |
4d4e536d52 | ||
![]() |
6fbd049941 | ||
![]() |
0e63757d19 | ||
![]() |
5787659b07 | ||
![]() |
b7d61f5778 | ||
![]() |
a3affccacd | ||
![]() |
93c88cc196 | ||
![]() |
5c5f9f7abd | ||
![]() |
6737aa9b83 | ||
![]() |
ae00aa8ed9 | ||
![]() |
42b247d5c0 | ||
![]() |
41801a73f6 | ||
![]() |
94e0d22bf2 | ||
![]() |
77192d84b1 | ||
![]() |
92ac4576ab | ||
![]() |
b5d7fa8183 | ||
![]() |
83e8a0eda6 | ||
![]() |
32f0456f21 | ||
![]() |
b34d7ee2f1 | ||
![]() |
083cb9429c | ||
![]() |
e7713615a5 | ||
![]() |
5d1f23c814 | ||
![]() |
b16af25052 | ||
![]() |
badebb9965 | ||
![]() |
8d6e8ddf55 | ||
![]() |
669c78a1db | ||
![]() |
531f8a2609 | ||
![]() |
9d59441dd0 | ||
![]() |
7c767b7769 | ||
![]() |
6833f59400 | ||
![]() |
2cb95a6959 | ||
![]() |
befb891174 | ||
![]() |
ff8df5e5b2 | ||
![]() |
43e4d53611 | ||
![]() |
9d8d909c18 | ||
![]() |
f081d96b0c | ||
![]() |
56c1789b30 | ||
![]() |
d1b817443c | ||
![]() |
a8abca1121 | ||
![]() |
708327ecd2 | ||
![]() |
dde58c798c | ||
![]() |
b91317046b | ||
![]() |
4b5d4b02c9 | ||
![]() |
b04b4dd864 | ||
![]() |
8cb9df7597 | ||
![]() |
b850510e5a | ||
![]() |
d04a7ac8fe | ||
![]() |
44561faea4 |
17 changed files with 743 additions and 170 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,4 @@
|
||||||
includes/config.inc.php
|
includes/config.inc.php
|
||||||
nsedit.sublime*
|
nsedit.sublime*
|
||||||
|
etc
|
||||||
|
templates.d/*.json
|
||||||
|
|
32
Dockerfile
32
Dockerfile
|
@ -1,38 +1,28 @@
|
||||||
FROM debian:jessie
|
FROM debian:bookworm
|
||||||
MAINTAINER Yury Evtikhov <yury@evtikhov.info>
|
MAINTAINER Yury Evtikhov <yury@evtikhov.info>
|
||||||
#
|
#
|
||||||
# This Dockerfile is intended only for test/development use.
|
# This Dockerfile is intended only for test/development use.
|
||||||
# It will be a really BAD idea to use it for production or public services.
|
# It will be a really BAD idea to use it for production or public services.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
|
||||||
#
|
|
||||||
# Please set the following variables before building:
|
|
||||||
#
|
|
||||||
ENV PDNSAPIPWD mypowerdnsapipassword
|
|
||||||
ENV PDNSAPIIP 192.168.1.2
|
|
||||||
ENV PDNSAPIPORT 8081
|
|
||||||
|
|
||||||
# Update and Upgrade system
|
# Update and Upgrade system
|
||||||
RUN apt-get -y update && \
|
RUN apt-get -y update && \
|
||||||
apt-get -y install curl git-core php5-cli php5-curl php5-json php5-sqlite && \
|
apt-get -y install curl git-core php8.2-cli php8.2-curl php8.2-sqlite3 && \
|
||||||
mkdir /app && \
|
rm -rf /var/lib/apt/lists/*
|
||||||
git clone --recursive https://github.com/tuxis-ie/nsedit.git /app/nsedit && \
|
RUN mkdir /app
|
||||||
cp /app/nsedit/includes/config.inc.php-dist /app/nsedit/includes/config.inc.php && \
|
RUN git clone --recursive https://github.com/tuxis-ie/nsedit.git /app/nsedit
|
||||||
sed "s/\$apipass = ''/\$apipass = '$PDNSAPIPWD'/" -i /app/nsedit/includes/config.inc.php && \
|
RUN cp /app/nsedit/includes/config.inc.php-dist /app/nsedit/includes/config.inc.php
|
||||||
sed "s/\$apiip = ''/\$apiip = '$PDNSAPIIP'/" -i /app/nsedit/includes/config.inc.php && \
|
COPY docker-entrypoint.sh /app/nsedit/docker-entrypoint.sh
|
||||||
sed "s/\$apiport = ''/\$apiport = '$PDNSAPIPORT'/" -i /app/nsedit/includes/config.inc.php && \
|
RUN chmod +x /app/nsedit/docker-entrypoint.sh
|
||||||
sed "s/\$authdb = \"\.\.\/etc\/pdns\.users\.sqlite3\"/\$authdb = \"\/app\/pdns\.users\.sqlite3\"/" -i /app/nsedit/includes/config.inc.php
|
|
||||||
|
|
||||||
# Define working directory.
|
# Define working directory.
|
||||||
VOLUME /app/nsedit
|
VOLUME /app/nsedit
|
||||||
WORKDIR /app/nsedit
|
WORKDIR /app/nsedit
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/php", "-S", "0.0.0.0:8080"]
|
CMD ["sh", "-c", "/app/nsedit/docker-entrypoint.sh"]
|
||||||
|
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
|
|
27
README.md
27
README.md
|
@ -19,7 +19,7 @@ Features
|
||||||
User support
|
User support
|
||||||
============
|
============
|
||||||
Multiple users are supported. A user can be an admin or a normal user. You can
|
Multiple users are supported. A user can be an admin or a normal user. You can
|
||||||
configure wheter or not a normal user is allowed to add new zones.
|
configure whether or not a normal user is allowed to add new zones.
|
||||||
|
|
||||||
WeFact Login support
|
WeFact Login support
|
||||||
====================
|
====================
|
||||||
|
@ -50,12 +50,35 @@ Installing
|
||||||
|
|
||||||
* Copy ```includes/config.inc.php-dist``` to ```includes/config.inc.php``` and edit config.inc.php to your needs.
|
* Copy ```includes/config.inc.php-dist``` to ```includes/config.inc.php``` and edit config.inc.php to your needs.
|
||||||
|
|
||||||
* By default, nsedit writes its user database to ../etc/pdns.users.sqlite3. Be sure that your webserver can create that directory and write to it.
|
* By default, nsedit writes its user database to ../etc/pdns.users.sqlite3. Be sure that your webserver can create that directory and write to it. **Make sure the Webserver doesn't serve this file/folder to the public!**
|
||||||
|
|
||||||
* Visit http(s)://<url>/nsedit/ and login with admin/admin (Don't forget to update your password!)
|
* Visit http(s)://<url>/nsedit/ and login with admin/admin (Don't forget to update your password!)
|
||||||
|
|
||||||
Have fun ;)
|
Have fun ;)
|
||||||
|
|
||||||
|
Other methods of installation (Unsupported)
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
* Baji Zsolt created a Suse image: https://susestudio.com/a/vvnMqa/powerdns-with-nsedit
|
||||||
|
* Yury Evtikhov created the Docker file: https://github.com/tuxis-ie/nsedit/blob/master/Dockerfile
|
||||||
|
|
||||||
|
Configuring PowerDNS
|
||||||
|
====================
|
||||||
|
Minimal configuration of PowerDNS for supporting nsedit has to include 3 directives:
|
||||||
|
```
|
||||||
|
webserver=yes
|
||||||
|
api=yes
|
||||||
|
api-key=SomeRandomString
|
||||||
|
```
|
||||||
|
|
||||||
|
Special note for Ubuntu Xenial Xerus 16.04 users:
|
||||||
|
Default `pdns` package included in Ubuntu repositories has the version of 4.0.0-alpha2 and *nsedit v1.0* doesn't work with it due to API incompatibility.
|
||||||
|
|
||||||
|
If your PowerDNS version is not the latest one, please consider adding PowerDNS repository to your system.
|
||||||
|
|
||||||
|
Detailed instructions for adding repository are available at http://repo.powerdns.com/
|
||||||
|
|
||||||
|
|
||||||
Screenshots
|
Screenshots
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ body, html {
|
||||||
border: 1px solid #DDD;
|
border: 1px solid #DDD;
|
||||||
font-family: 'Segoe UI Semilight','Open Sans',Verdana,Arial,Helvetica,sans-serif;
|
font-family: 'Segoe UI Semilight','Open Sans',Verdana,Arial,Helvetica,sans-serif;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
float: left;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
width: 10%;
|
width: 10%;
|
||||||
|
|
13
docker-entrypoint.sh
Normal file
13
docker-entrypoint.sh
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
[ -z "$PDNSAPIIP" ] && echo "Set PDNSAPIIP to your PowerDNS API IP/Hostname" && exit 1;
|
||||||
|
[ -z "$PDNSAPIPWD" ] && echo "Set PDNSAPIPWD to your PowerDNS API Password" && exit 1;
|
||||||
|
|
||||||
|
sed "s/\$apipass = ''/\$apipass = '$PDNSAPIPWD'/" -i /app/nsedit/includes/config.inc.php
|
||||||
|
sed "s/\$apiip = ''/\$apiip = '$PDNSAPIIP'/" -i /app/nsedit/includes/config.inc.php
|
||||||
|
if [[ $PDNSAPIPORT && ${PDNSAPIPORT-x} ]]
|
||||||
|
then
|
||||||
|
sed "s/\$apiport = '8081'/\$apiport = '$PDNSAPIPORT'/" -i /app/nsedit/includes/config.inc.php
|
||||||
|
fi
|
||||||
|
sed "s/\$authdb = \"\.\.\/etc\/pdns\.users\.sqlite3\"/\$authdb = \"\/app\/pdns\.users\.sqlite3\"/" -i /app/nsedit/includes/config.inc.php
|
||||||
|
|
||||||
|
exec /usr/bin/php -S 0.0.0.0:8080
|
|
@ -3,6 +3,19 @@
|
||||||
include_once('includes/config.inc.php');
|
include_once('includes/config.inc.php');
|
||||||
|
|
||||||
class ApiHandler {
|
class ApiHandler {
|
||||||
|
public $headers;
|
||||||
|
public $hostname;
|
||||||
|
public $port;
|
||||||
|
public $auth;
|
||||||
|
public $proto;
|
||||||
|
public $sslverify;
|
||||||
|
public $curlh;
|
||||||
|
public $method;
|
||||||
|
public $content;
|
||||||
|
public $apiurl;
|
||||||
|
public $url;
|
||||||
|
public $json;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
global $apiip, $apiport, $apipass, $apiproto, $apisslverify;
|
global $apiip, $apiport, $apipass, $apiproto, $apisslverify;
|
||||||
|
|
||||||
|
@ -29,22 +42,21 @@ class ApiHandler {
|
||||||
private function apiurl() {
|
private function apiurl() {
|
||||||
$tmp = new ApiHandler();
|
$tmp = new ApiHandler();
|
||||||
|
|
||||||
$tmp->url = '/api';
|
$tmp->url = '/api/v1/servers/localhost';
|
||||||
$tmp->go();
|
$tmp->go();
|
||||||
|
|
||||||
if ($tmp->json[0]['version'] <= 1) {
|
$this->apiurl = $tmp->json["url"];
|
||||||
$this->apiurl = $tmp->json[0]['url'];
|
|
||||||
} else {
|
|
||||||
throw new Exception("Unsupported API version");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function curlopts() {
|
private function curlopts() {
|
||||||
$this->authheaders();
|
$this->authheaders();
|
||||||
$this->addheader('Accept', 'application/json');
|
$this->addheader('Accept', 'application/json');
|
||||||
|
|
||||||
curl_reset($this->curlh);
|
if(defined('curl_reset')) {
|
||||||
|
curl_reset($this->curlh);
|
||||||
|
} else {
|
||||||
|
$this->curlh = curl_init();
|
||||||
|
}
|
||||||
curl_setopt($this->curlh, CURLOPT_HTTPHEADER, Array());
|
curl_setopt($this->curlh, CURLOPT_HTTPHEADER, Array());
|
||||||
curl_setopt($this->curlh, CURLOPT_RETURNTRANSFER, 1);
|
curl_setopt($this->curlh, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
|
||||||
|
@ -61,7 +73,13 @@ class ApiHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function baseurl() {
|
private function baseurl() {
|
||||||
return $this->proto.'://'.$this->hostname.':'.$this->port.$this->apiurl;
|
$ip = $this->hostname;
|
||||||
|
|
||||||
|
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||||
|
$ip = sprintf('[%s]', $ip); // curl needs brackets for IPv6
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->proto.'://'.$ip.':'.$this->port.$this->apiurl;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function go() {
|
private function go() {
|
||||||
|
@ -89,12 +107,6 @@ class ApiHandler {
|
||||||
|
|
||||||
curl_setopt($this->curlh, CURLOPT_URL, $this->baseurl().$this->url);
|
curl_setopt($this->curlh, CURLOPT_URL, $this->baseurl().$this->url);
|
||||||
|
|
||||||
//print "Here we go:\n";
|
|
||||||
//print "Request: ".$this->method.' '.$this->baseurl().$this->url."\n";
|
|
||||||
//if ($this->content != '') {
|
|
||||||
// print "Content: ".$this->content."\n";
|
|
||||||
//}
|
|
||||||
|
|
||||||
$return = curl_exec($this->curlh);
|
$return = curl_exec($this->curlh);
|
||||||
$code = curl_getinfo($this->curlh, CURLINFO_HTTP_CODE);
|
$code = curl_getinfo($this->curlh, CURLINFO_HTTP_CODE);
|
||||||
$json = json_decode($return, 1);
|
$json = json_decode($return, 1);
|
||||||
|
@ -112,12 +124,11 @@ class ApiHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function call() {
|
public function call() {
|
||||||
if (substr($this->url, 0, 1) == '/') {
|
if (substr($this->url, 0, 1) != '/') {
|
||||||
$this->apiurl();
|
$this->url = '/'.$this->url;
|
||||||
} else {
|
|
||||||
$this->apiurl = '/';
|
|
||||||
}
|
}
|
||||||
|
$this->apiurl();
|
||||||
|
$this->url = str_replace($this->apiurl, '', $this->url);
|
||||||
$this->go();
|
$this->go();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
include_once('ApiHandler.php');
|
include_once('ApiHandler.php');
|
||||||
|
|
||||||
class PdnsAPI {
|
class PdnsAPI {
|
||||||
|
public $http;
|
||||||
|
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->http = new ApiHandler();
|
$this->http = new ApiHandler();
|
||||||
}
|
}
|
||||||
|
@ -11,7 +14,7 @@ class PdnsAPI {
|
||||||
$api = clone $this->http;
|
$api = clone $this->http;
|
||||||
$api->method = 'GET';
|
$api->method = 'GET';
|
||||||
if ($q) {
|
if ($q) {
|
||||||
$api->url = "/servers/localhost/search-data?q=*".$q."*&max=25";
|
$api->url = "/search-data?q=*".$q."*&max=25";
|
||||||
$api->call();
|
$api->call();
|
||||||
$ret = Array();
|
$ret = Array();
|
||||||
$seen = Array();
|
$seen = Array();
|
||||||
|
@ -28,7 +31,7 @@ class PdnsAPI {
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
$api->url = "/servers/localhost/zones";
|
$api->url = "/zones";
|
||||||
$api->call();
|
$api->call();
|
||||||
|
|
||||||
return $api->json;
|
return $api->json;
|
||||||
|
@ -37,7 +40,7 @@ class PdnsAPI {
|
||||||
public function loadzone($zoneid) {
|
public function loadzone($zoneid) {
|
||||||
$api = clone $this->http;
|
$api = clone $this->http;
|
||||||
$api->method = 'GET';
|
$api->method = 'GET';
|
||||||
$api->url = "/servers/localhost/zones/$zoneid";
|
$api->url = "/zones/$zoneid";
|
||||||
$api->call();
|
$api->call();
|
||||||
|
|
||||||
return $api->json;
|
return $api->json;
|
||||||
|
@ -46,7 +49,7 @@ class PdnsAPI {
|
||||||
public function exportzone($zoneid) {
|
public function exportzone($zoneid) {
|
||||||
$api = clone $this->http;
|
$api = clone $this->http;
|
||||||
$api->method = 'GET';
|
$api->method = 'GET';
|
||||||
$api->url = "/servers/localhost/zones/$zoneid/export";
|
$api->url = "/zones/$zoneid/export";
|
||||||
$api->call();
|
$api->call();
|
||||||
|
|
||||||
return $api->json;
|
return $api->json;
|
||||||
|
@ -64,7 +67,7 @@ class PdnsAPI {
|
||||||
|
|
||||||
if (!isset($zone['serial']) or gettype($zone['serial']) != 'integer') {
|
if (!isset($zone['serial']) or gettype($zone['serial']) != 'integer') {
|
||||||
$api->method = 'POST';
|
$api->method = 'POST';
|
||||||
$api->url = '/servers/localhost/zones';
|
$api->url = '/zones';
|
||||||
$api->content = json_encode($zonedata);
|
$api->content = json_encode($zonedata);
|
||||||
$api->call();
|
$api->call();
|
||||||
|
|
||||||
|
@ -88,7 +91,7 @@ class PdnsAPI {
|
||||||
public function deletezone($zoneid) {
|
public function deletezone($zoneid) {
|
||||||
$api = clone $this->http;
|
$api = clone $this->http;
|
||||||
$api->method = 'DELETE';
|
$api->method = 'DELETE';
|
||||||
$api->url = "/servers/localhost/zones/$zoneid";
|
$api->url = "/zones/$zoneid";
|
||||||
$api->call();
|
$api->call();
|
||||||
|
|
||||||
return $api->json;
|
return $api->json;
|
||||||
|
@ -98,7 +101,7 @@ class PdnsAPI {
|
||||||
$ret = array();
|
$ret = array();
|
||||||
$api = clone $this->http;
|
$api = clone $this->http;
|
||||||
$api->method = 'GET';
|
$api->method = 'GET';
|
||||||
$api->url = "/servers/localhost/zones/$zoneid/cryptokeys";
|
$api->url = "/zones/$zoneid/cryptokeys";
|
||||||
|
|
||||||
$api->call();
|
$api->call();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
class Zone {
|
class Zone {
|
||||||
|
public $id;
|
||||||
|
public $name;
|
||||||
|
public $kind;
|
||||||
|
public $url;
|
||||||
|
public $serial;
|
||||||
|
public $dnssec;
|
||||||
|
public $soa_edit;
|
||||||
|
public $soa_edit_api;
|
||||||
|
public $keyinfo;
|
||||||
|
public $account;
|
||||||
|
public $zone;
|
||||||
|
public $nameservers;
|
||||||
|
public $rrsets;
|
||||||
|
public $masters;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->id = '';
|
$this->id = '';
|
||||||
$this->name = '';
|
$this->name = '';
|
||||||
|
@ -26,10 +41,10 @@ class Zone {
|
||||||
$this->setAccount($data['account']);
|
$this->setAccount($data['account']);
|
||||||
$this->setSerial($data['serial']);
|
$this->setSerial($data['serial']);
|
||||||
$this->url = $data['url'];
|
$this->url = $data['url'];
|
||||||
if (isset($data['soa_edit']))
|
if (isset($data['soa_edit']) && $data['soa_edit'] != "")
|
||||||
$this->setSoaEdit($data['soa_edit']);
|
$this->setSoaEdit($data['soa_edit']);
|
||||||
if (isset($data['soa_edit_api']))
|
if (isset($data['soa_edit_api']) && $data['soa_edit_api'] != "")
|
||||||
$this->setSoaEditApi($data['soa_edit_api']);
|
$this->setSoaEditApi($data['soa_edit_api'], True);
|
||||||
|
|
||||||
foreach ($data['masters'] as $master) {
|
foreach ($data['masters'] as $master) {
|
||||||
$this->addMaster($master);
|
$this->addMaster($master);
|
||||||
|
@ -76,7 +91,12 @@ class Zone {
|
||||||
$this->soa_edit = $soaedit;
|
$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;
|
$this->soa_edit_api = $soaeditapi;
|
||||||
}
|
}
|
||||||
public function setName($name) {
|
public function setName($name) {
|
||||||
|
@ -125,6 +145,7 @@ class Zone {
|
||||||
|
|
||||||
if ($rrset) {
|
if ($rrset) {
|
||||||
$rrset->addRecord($content, $disabled, $setptr);
|
$rrset->addRecord($content, $disabled, $setptr);
|
||||||
|
$rrset->setTtl($ttl);
|
||||||
} else {
|
} else {
|
||||||
$this->addRRSet($name, $type, $content, $disabled, $ttl, $setptr);
|
$this->addRRSet($name, $type, $content, $disabled, $ttl, $setptr);
|
||||||
}
|
}
|
||||||
|
@ -180,8 +201,12 @@ class Zone {
|
||||||
$ret['nameservers'] = $this->nameservers;
|
$ret['nameservers'] = $this->nameservers;
|
||||||
$ret['kind'] = $this->kind;
|
$ret['kind'] = $this->kind;
|
||||||
$ret['name'] = $this->name;
|
$ret['name'] = $this->name;
|
||||||
$ret['soa_edit'] = $this->soa_edit;
|
if (isset($this->soa_edit) && $this->soa_edit != "") {
|
||||||
$ret['soa_edit_api'] = $this->soa_edit_api;
|
$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) {
|
if ($this->zone) {
|
||||||
$ret['zone'] = $this->zone;
|
$ret['zone'] = $this->zone;
|
||||||
return $ret;
|
return $ret;
|
||||||
|
@ -211,6 +236,13 @@ class Zone {
|
||||||
}
|
}
|
||||||
|
|
||||||
class RRSet {
|
class RRSet {
|
||||||
|
public $name;
|
||||||
|
public $type;
|
||||||
|
public $ttl;
|
||||||
|
public $changetype;
|
||||||
|
public $records;
|
||||||
|
public $comments;
|
||||||
|
|
||||||
public function __construct($name = '', $type = '', $content = '', $disabled = FALSE, $ttl = 3600, $setptr = FALSE) {
|
public function __construct($name = '', $type = '', $content = '', $disabled = FALSE, $ttl = 3600, $setptr = FALSE) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->type = $type;
|
$this->type = $type;
|
||||||
|
@ -239,7 +271,7 @@ class RRSet {
|
||||||
public function addRecord($content, $disabled = FALSE, $setptr = FALSE) {
|
public function addRecord($content, $disabled = FALSE, $setptr = FALSE) {
|
||||||
foreach ($this->records as $record) {
|
foreach ($this->records as $record) {
|
||||||
if ($record->content == $content) {
|
if ($record->content == $content) {
|
||||||
throw Exception("Record already exists");
|
throw new Exception($this->name."/".$this->type." has duplicate records.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,6 +328,10 @@ class RRSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Record {
|
class Record {
|
||||||
|
public $content;
|
||||||
|
public $disabled;
|
||||||
|
public $setptr;
|
||||||
|
|
||||||
public function __construct($content, $disabled = FALSE, $setptr = FALSE) {
|
public function __construct($content, $disabled = FALSE, $setptr = FALSE) {
|
||||||
$this->content = $content;
|
$this->content = $content;
|
||||||
$this->disabled = $disabled;
|
$this->disabled = $disabled;
|
||||||
|
@ -316,6 +352,10 @@ class Record {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Comment {
|
class Comment {
|
||||||
|
public $content;
|
||||||
|
public $account;
|
||||||
|
public $modified_at;
|
||||||
|
|
||||||
public function __construct($content, $account, $modified_at) {
|
public function __construct($content, $account, $modified_at) {
|
||||||
$this->content = $content;
|
$this->content = $content;
|
||||||
$this->account = $account;
|
$this->account = $account;
|
||||||
|
@ -328,6 +368,8 @@ class Comment {
|
||||||
$ret['content'] = $this->content;
|
$ret['content'] = $this->content;
|
||||||
$ret['account'] = $this->account;
|
$ret['account'] = $this->account;
|
||||||
$ret['modified_at'] = $this->modified_at;
|
$ret['modified_at'] = $this->modified_at;
|
||||||
|
|
||||||
|
return $ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,12 @@ $apiproto = 'http'; # http | https
|
||||||
$apisslverify = FALSE; # Verify SSL Certificate if using https for apiproto
|
$apisslverify = FALSE; # Verify SSL Certificate if using https for apiproto
|
||||||
$allowzoneadd = FALSE; # Allow normal users to add zones
|
$allowzoneadd = FALSE; # Allow normal users to add zones
|
||||||
$logging = TRUE;
|
$logging = TRUE;
|
||||||
|
$allowclearlogs = TRUE; # Allow clearing of log entries
|
||||||
|
$allowrotatelogs = FALSE;# Allow rotation to text file on server
|
||||||
|
|
||||||
|
# Log directory - if allowrotatelogs is set, this is where the logs will
|
||||||
|
# be written. It must be writeable by the web server user.
|
||||||
|
$logsdirectory = "../etc";
|
||||||
|
|
||||||
# If you configure this, nsedit will try to authenticate via WeFact too.
|
# If you configure this, nsedit will try to authenticate via WeFact too.
|
||||||
# Debtors will be added to the sqlitedatabase with their crypted password.
|
# Debtors will be added to the sqlitedatabase with their crypted password.
|
||||||
|
@ -19,8 +24,13 @@ $logging = TRUE;
|
||||||
#$adminapiips = array();
|
#$adminapiips = array();
|
||||||
#$adminapikey = 'thisshouldbequitealongstring,youknow';
|
#$adminapikey = 'thisshouldbequitealongstring,youknow';
|
||||||
|
|
||||||
|
# Location of user-database. Make sure its writeable and not served by the webserver!
|
||||||
$authdb = "../etc/pdns.users.sqlite3";
|
$authdb = "../etc/pdns.users.sqlite3";
|
||||||
|
|
||||||
|
# Admin login and password at first start-up
|
||||||
|
$default_admin_username = "admin";
|
||||||
|
$default_admin_password = "admin";
|
||||||
|
|
||||||
# Set a random generated secret to enable auto-login and long living csrf tokens
|
# Set a random generated secret to enable auto-login and long living csrf tokens
|
||||||
// $secret = '...';
|
// $secret = '...';
|
||||||
|
|
||||||
|
@ -30,16 +40,24 @@ $templates[] = array(
|
||||||
'name' => 'Tuxis',
|
'name' => 'Tuxis',
|
||||||
'owner' => 'username', # Set to 'public' to make it available to all users
|
'owner' => 'username', # Set to 'public' to make it available to all users
|
||||||
'records' => array(
|
'records' => array(
|
||||||
array(
|
array(
|
||||||
'name' => '',
|
'name' => '',
|
||||||
'type' => 'MX',
|
'type' => 'MX',
|
||||||
'content' => '200 mx2.tuxis.nl')
|
'content' => '200 mx2.tuxis.nl.'),
|
||||||
|
array(
|
||||||
|
'name' => '',
|
||||||
|
'type' => 'A',
|
||||||
|
'content' => '1.2.3.4'),
|
||||||
|
array(
|
||||||
|
'name' => 'www',
|
||||||
|
'type' => 'CNAME',
|
||||||
|
'content' => '[zonename]')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$defaults['soa_edit'] = 'INCEPTION-INCREMENT';
|
$defaults['soa_edit'] = 'INCEPTION-INCREMENT';
|
||||||
$defaults['soa_edit_api'] = 'INCEPTION-INCREMENT';
|
$defaults['soa_edit_api'] = 'DEFAULT';
|
||||||
$defaults['defaulttype'] = 'Master'; # Choose between 'Native' or 'Master'
|
$defaults['defaulttype'] = 'Master'; # Choose between 'Native' or 'Master'
|
||||||
$defaults['ns'][0] = 'unconfigured.primaryns.'; # The value of the first NS-record
|
$defaults['ns'][0] = 'unconfigured.primaryns.'; # The value of the first NS-record
|
||||||
$defaults['ns'][1] = 'unconfigured.secondaryns.'; # The value of the second NS-record
|
$defaults['ns'][1] = 'unconfigured.secondaryns.'; # The value of the second NS-record
|
||||||
|
|
|
@ -35,7 +35,7 @@ if (isset($defaults['primaryns'])) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($logo) or empty($logo)) {
|
if (!isset($logo) or empty($logo)) {
|
||||||
$logo = 'http://www.tuxis.nl/uploads/images/nsedit.png';
|
$logo = 'https://www.tuxis.nl/uploads/images/nsedit.png';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ if (class_exists('SQLite3') === FALSE) {
|
||||||
$errormsg = "You need PHP SQLite3 to run nsedit";
|
$errormsg = "You need PHP SQLite3 to run nsedit";
|
||||||
$blocklogin = TRUE;
|
$blocklogin = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('openssl_random_pseudo_bytes') === FALSE) {
|
if (function_exists('openssl_random_pseudo_bytes') === FALSE) {
|
||||||
$errormsg = "You need PHP compiled with openssl to run nsedit";
|
$errormsg = "You need PHP compiled with openssl to run nsedit";
|
||||||
$blocklogin = TRUE;
|
$blocklogin = TRUE;
|
||||||
|
@ -59,13 +59,20 @@ if (function_exists('openssl_random_pseudo_bytes') === FALSE) {
|
||||||
|
|
||||||
$defaults['defaulttype'] = ucfirst(strtolower($defaults['defaulttype']));
|
$defaults['defaulttype'] = ucfirst(strtolower($defaults['defaulttype']));
|
||||||
|
|
||||||
if (isset($authdb) && !file_exists($authdb) && class_exists('SQLite3')) {
|
try {
|
||||||
is_dir(dirname($authdb)) || mkdir(dirname($authdb));
|
if (isset($authdb) && !file_exists($authdb) && class_exists('SQLite3')) {
|
||||||
$db = new SQLite3($authdb, SQLITE3_OPEN_CREATE|SQLITE3_OPEN_READWRITE);
|
is_dir(dirname($authdb)) || mkdir(dirname($authdb));
|
||||||
$createsql = file_get_contents('includes/scheme.sql');
|
$db = new SQLite3($authdb, SQLITE3_OPEN_CREATE|SQLITE3_OPEN_READWRITE);
|
||||||
$db->exec($createsql);
|
$createsql = file_get_contents('includes/scheme.sql');
|
||||||
$salt = bin2hex(openssl_random_pseudo_bytes(16));
|
$db->exec($createsql);
|
||||||
$db->exec("INSERT INTO users (emailaddress, password, isadmin) VALUES ('admin', '".crypt("admin", '$6$'.$salt)."', 1)");
|
$salt = bin2hex(openssl_random_pseudo_bytes(16));
|
||||||
|
$default_admin_username = $default_admin_username ?? "admin";
|
||||||
|
$default_admin_password = $default_admin_password ?? "admin";
|
||||||
|
$db->exec("INSERT INTO users (emailaddress, password, isadmin) VALUES ('".$default_admin_username."', '".crypt($default_admin_password, '$6$'.$salt)."', 1)");
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
print("We have issues getting the authdb working: $e");
|
||||||
|
$blocklogin = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
function string_starts_with($string, $prefix)
|
function string_starts_with($string, $prefix)
|
||||||
|
@ -85,10 +92,12 @@ function string_ends_with($string, $suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_db() {
|
function get_db() {
|
||||||
global $authdb;
|
global $authdb, $db;
|
||||||
|
|
||||||
$db = new SQLite3($authdb, SQLITE3_OPEN_READWRITE);
|
if (!isset($db)) {
|
||||||
$db->exec('PRAGMA foreign_keys = 1');
|
$db = new SQLite3($authdb, SQLITE3_OPEN_READWRITE);
|
||||||
|
$db->exec('PRAGMA foreign_keys = 1');
|
||||||
|
}
|
||||||
|
|
||||||
return $db;
|
return $db;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +119,6 @@ function get_user_info($u) {
|
||||||
$q->bindValue(1, $u);
|
$q->bindValue(1, $u);
|
||||||
$result = $q->execute();
|
$result = $q->execute();
|
||||||
$userinfo = $result->fetchArray(SQLITE3_ASSOC);
|
$userinfo = $result->fetchArray(SQLITE3_ASSOC);
|
||||||
$db->close();
|
|
||||||
|
|
||||||
return $userinfo;
|
return $userinfo;
|
||||||
}
|
}
|
||||||
|
@ -125,10 +133,8 @@ function do_db_auth($u, $p) {
|
||||||
$q->bindValue(1, $u);
|
$q->bindValue(1, $u);
|
||||||
$result = $q->execute();
|
$result = $q->execute();
|
||||||
$userinfo = $result->fetchArray(SQLITE3_ASSOC);
|
$userinfo = $result->fetchArray(SQLITE3_ASSOC);
|
||||||
$db->close();
|
|
||||||
|
|
||||||
if ($userinfo and $userinfo['password'] and (crypt($p, $userinfo['password']) === $userinfo['password'])) {
|
if ($userinfo and $userinfo['password'] and (crypt($p, $userinfo['password']) === $userinfo['password'])) {
|
||||||
writelog('Succesful login.');
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +156,6 @@ function add_user($username, $isadmin = FALSE, $password = '') {
|
||||||
$q->bindValue(2, $password, SQLITE3_TEXT);
|
$q->bindValue(2, $password, SQLITE3_TEXT);
|
||||||
$q->bindValue(3, (int)(bool) $isadmin, SQLITE3_INTEGER);
|
$q->bindValue(3, (int)(bool) $isadmin, SQLITE3_INTEGER);
|
||||||
$ret = $q->execute();
|
$ret = $q->execute();
|
||||||
$db->close();
|
|
||||||
|
|
||||||
if ($isadmin) {
|
if ($isadmin) {
|
||||||
writelog("Added user $username as admin.");
|
writelog("Added user $username as admin.");
|
||||||
|
@ -160,7 +165,7 @@ function add_user($username, $isadmin = FALSE, $password = '') {
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_user($username, $isadmin, $password) {
|
function update_user($id, $isadmin, $password) {
|
||||||
if ($password && !preg_match('/\$6\$/', $password)) {
|
if ($password && !preg_match('/\$6\$/', $password)) {
|
||||||
$salt = bin2hex(openssl_random_pseudo_bytes(16));
|
$salt = bin2hex(openssl_random_pseudo_bytes(16));
|
||||||
$password = crypt($password, '$6$'.$salt);
|
$password = crypt($password, '$6$'.$salt);
|
||||||
|
@ -168,33 +173,49 @@ function update_user($username, $isadmin, $password) {
|
||||||
|
|
||||||
$db = get_db();
|
$db = get_db();
|
||||||
|
|
||||||
|
$q = $db->prepare('SELECT * FROM users WHERE id = ?');
|
||||||
|
$q->bindValue(1, $id, SQLITE3_INTEGER);
|
||||||
|
$result = $q->execute();
|
||||||
|
$userinfo = $result->fetchArray(SQLITE3_ASSOC);
|
||||||
|
$q->close();
|
||||||
|
$username = $userinfo['emailaddress'];
|
||||||
|
|
||||||
if ($password) {
|
if ($password) {
|
||||||
$q = $db->prepare('UPDATE users SET isadmin = ?, password = ? WHERE emailaddress = ?');
|
$q = $db->prepare('UPDATE users SET isadmin = ?, password = ? WHERE id = ?');
|
||||||
$q->bindValue(1, (int)(bool)$isadmin, SQLITE3_INTEGER);
|
$q->bindValue(1, (int)(bool)$isadmin, SQLITE3_INTEGER);
|
||||||
$q->bindValue(2, $password, SQLITE3_TEXT);
|
$q->bindValue(2, $password, SQLITE3_TEXT);
|
||||||
$q->bindValue(3, $username, SQLITE3_TEXT);
|
$q->bindValue(3, $id, SQLITE3_INTEGER);
|
||||||
writelog("Updating password and/or settings for $username. Admin: ".(int)(bool)$isadmin);
|
writelog("Updating password and/or settings for $username. Admin: ".(int)(bool)$isadmin);
|
||||||
} else {
|
} else {
|
||||||
$q = $db->prepare('UPDATE users SET isadmin = ? WHERE emailaddress = ?');
|
$q = $db->prepare('UPDATE users SET isadmin = ? WHERE id = ?');
|
||||||
$q->bindValue(1, (int)(bool)$isadmin, SQLITE3_INTEGER);
|
$q->bindValue(1, (int)(bool)$isadmin, SQLITE3_INTEGER);
|
||||||
$q->bindValue(2, $username, SQLITE3_TEXT);
|
$q->bindValue(2, $id, SQLITE3_INTEGER);
|
||||||
writelog("Updating settings for $username. Admin: ".(int)(bool)$isadmin);
|
writelog("Updating settings for $username. Admin: ".(int)(bool)$isadmin);
|
||||||
}
|
}
|
||||||
$ret = $q->execute();
|
$ret = $q->execute();
|
||||||
$db->close();
|
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
function delete_user($username) {
|
function delete_user($id) {
|
||||||
$db = get_db();
|
$db = get_db();
|
||||||
$q = $db->prepare('DELETE FROM users WHERE id = ?');
|
|
||||||
$q->bindValue(1, $id, SQLITE3_INTEGER);
|
|
||||||
$ret = $q->execute();
|
|
||||||
$db->close();
|
|
||||||
|
|
||||||
writelog("Deleted user $username.");
|
$q = $db->prepare('SELECT * FROM users WHERE id = ?');
|
||||||
return $ret;
|
$q->bindValue(1, $id, SQLITE3_INTEGER);
|
||||||
|
$result = $q->execute();
|
||||||
|
$userinfo = $result->fetchArray(SQLITE3_ASSOC);
|
||||||
|
$q->close();
|
||||||
|
|
||||||
|
if($userinfo) {
|
||||||
|
$q = $db->prepare('DELETE FROM users WHERE id = ?');
|
||||||
|
$q->bindValue(1, $id, SQLITE3_INTEGER);
|
||||||
|
$ret = $q->execute();
|
||||||
|
|
||||||
|
writelog("Deleted user " . $userinfo['emailaddress'] . ".");
|
||||||
|
return $ret;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function valid_user($name) {
|
function valid_user($name) {
|
||||||
|
@ -224,6 +245,8 @@ function jtable_respond($records, $method = 'multiple', $msg = 'Undefined errorm
|
||||||
$jTableResult['RecordCount'] = count($records);
|
$jTableResult['RecordCount'] = count($records);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$db = get_db();
|
||||||
|
$db->close();
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
print json_encode($jTableResult);
|
print json_encode($jTableResult);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -232,6 +255,27 @@ function jtable_respond($records, $method = 'multiple', $msg = 'Undefined errorm
|
||||||
function user_template_list() {
|
function user_template_list() {
|
||||||
global $templates;
|
global $templates;
|
||||||
|
|
||||||
|
if (is_dir("templates.d")) {
|
||||||
|
if ($templdir=opendir("templates.d")) {
|
||||||
|
while ($entry = readdir($templdir)) {
|
||||||
|
if (!str_ends_with($entry, ".json")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$f=file_get_contents("templates.d/$entry");
|
||||||
|
if ($f === false) {
|
||||||
|
error_log("Error reading file templates.d/$entry", 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$t = json_decode($f, true);
|
||||||
|
if ($t === null) {
|
||||||
|
error_log("Error decoding templates.d/$entry", 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
array_push($templates, $t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$templatelist = array();
|
$templatelist = array();
|
||||||
foreach ($templates as $template) {
|
foreach ($templates as $template) {
|
||||||
if (is_adminuser()
|
if (is_adminuser()
|
||||||
|
@ -273,15 +317,70 @@ function clearlogs() {
|
||||||
|
|
||||||
$db = get_db();
|
$db = get_db();
|
||||||
$q = $db->query('DELETE FROM logs;');
|
$q = $db->query('DELETE FROM logs;');
|
||||||
$db->close();
|
|
||||||
writelog("Logtable truncated.");
|
writelog("Logtable truncated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function writelog($line) {
|
function rotatelogs() {
|
||||||
|
global $logging, $logsdirectory;
|
||||||
|
if ($logging !== TRUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if(!is_dir($logsdirectory) || !is_writable($logsdirectory)) {
|
||||||
|
writelog("Logs directory cannot be written to.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
$filename = date("Y-m-d-His") . ".json";
|
||||||
|
$file = fopen($logsdirectory . "/" . $filename, "x");
|
||||||
|
|
||||||
|
if($file === FALSE) {
|
||||||
|
writelog("Can't create file for log rotation.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fwrite($file,json_encode(getlogs())) === FALSE) {
|
||||||
|
writelog("Can't write to file for log rotation.");
|
||||||
|
fclose($file);
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
fclose($file);
|
||||||
|
clearlogs();
|
||||||
|
return $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function listrotatedlogs() {
|
||||||
|
global $logging, $logsdirectory;
|
||||||
|
if ($logging !== TRUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
$list = scandir($logsdirectory,SCANDIR_SORT_DESCENDING);
|
||||||
|
|
||||||
|
if($list === FALSE) {
|
||||||
|
writelog("Logs directory cannot read.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$list=array_filter($list,
|
||||||
|
function ($val) {
|
||||||
|
return(preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{6}\.json/',$val) == 1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writelog($line, $user=False) {
|
||||||
global $logging;
|
global $logging;
|
||||||
if ($logging !== TRUE)
|
if ($logging !== TRUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ($user === False) {
|
||||||
|
$user = get_sess_user();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db = get_db();
|
$db = get_db();
|
||||||
$q = $db->prepare('CREATE TABLE IF NOT EXISTS logs (
|
$q = $db->prepare('CREATE TABLE IF NOT EXISTS logs (
|
||||||
|
@ -292,10 +391,9 @@ function writelog($line) {
|
||||||
$ret = $q->execute();
|
$ret = $q->execute();
|
||||||
|
|
||||||
$q = $db->prepare('INSERT INTO logs (user, log) VALUES (:user, :log)');
|
$q = $db->prepare('INSERT INTO logs (user, log) VALUES (:user, :log)');
|
||||||
$q->bindValue(':user', get_sess_user(), SQLITE3_TEXT);
|
$q->bindValue(':user', $user, SQLITE3_TEXT);
|
||||||
$q->bindValue(':log', $line, SQLITE3_TEXT);
|
$q->bindValue(':log', $line, SQLITE3_TEXT);
|
||||||
$q->execute();
|
$q->execute();
|
||||||
$db->close();
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return jtable_respond(null, 'error', $e->getMessage());
|
return jtable_respond(null, 'error', $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,13 @@ global $current_user;
|
||||||
$current_user = false;
|
$current_user = false;
|
||||||
|
|
||||||
// session startup
|
// session startup
|
||||||
function _set_current_user($username, $is_admin = false, $has_csrf_token = false, $is_api = false) {
|
function _set_current_user($username, $userid, $localauth = true, $is_admin = false, $has_csrf_token = false, $is_api = false) {
|
||||||
global $current_user;
|
global $current_user;
|
||||||
|
|
||||||
$current_user = array(
|
$current_user = array(
|
||||||
'username' => $username,
|
'username' => $username,
|
||||||
|
'id' => $userid,
|
||||||
|
'localauth' => $localauth,
|
||||||
'is_admin' => $is_admin,
|
'is_admin' => $is_admin,
|
||||||
'has_csrf_token' => $has_csrf_token,
|
'has_csrf_token' => $has_csrf_token,
|
||||||
'is_api' => $is_api,
|
'is_api' => $is_api,
|
||||||
|
@ -50,7 +52,7 @@ function _check_csrf_token($user) {
|
||||||
}
|
}
|
||||||
|
|
||||||
define('CSRF_TOKEN', $csrf_token);
|
define('CSRF_TOKEN', $csrf_token);
|
||||||
header("X-CSRF-Token: ${csrf_token}");
|
header("X-CSRF-Token: {$csrf_token}");
|
||||||
}
|
}
|
||||||
|
|
||||||
function enc_secret($message) {
|
function enc_secret($message) {
|
||||||
|
@ -120,13 +122,13 @@ function dec_secret($code) {
|
||||||
|
|
||||||
function _unset_cookie($name) {
|
function _unset_cookie($name) {
|
||||||
$is_ssl = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off';
|
$is_ssl = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off';
|
||||||
setcookie($name, null, -1, null, null, $is_ssl);
|
setcookie($name, "", -1, "", "", $is_ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _store_auto_login($value) {
|
function _store_auto_login($value) {
|
||||||
$is_ssl = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off';
|
$is_ssl = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off';
|
||||||
// set for 30 days
|
// set for 30 days
|
||||||
setcookie('NSEDIT_AUTOLOGIN', $value, time()+60*60*24*30, null, null, $is_ssl);
|
setcookie('NSEDIT_AUTOLOGIN', $value, time()+60*60*24*30, "", "", $is_ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
function try_login() {
|
function try_login() {
|
||||||
|
@ -150,6 +152,7 @@ function _try_login($username, $password) {
|
||||||
global $wefactapiurl, $wefactapikey;
|
global $wefactapiurl, $wefactapikey;
|
||||||
|
|
||||||
if (!valid_user($username)) {
|
if (!valid_user($username)) {
|
||||||
|
writelog("Illegal username at login!", $username);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +161,7 @@ function _try_login($username, $password) {
|
||||||
if (isset($wefactapiurl) && isset($wefactapikey)) {
|
if (isset($wefactapiurl) && isset($wefactapikey)) {
|
||||||
$wefact = do_wefact_auth($username, $password);
|
$wefact = do_wefact_auth($username, $password);
|
||||||
if (false === $wefact ) {
|
if (false === $wefact ) {
|
||||||
|
writelog("Failed Wefact login!", $username);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (-1 !== $wefact) {
|
if (-1 !== $wefact) {
|
||||||
|
@ -166,14 +170,16 @@ function _try_login($username, $password) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($do_local_auth && !do_db_auth($username, $password)) {
|
if ($do_local_auth && !do_db_auth($username, $password)) {
|
||||||
|
writelog("Failed login!", $username);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = get_user_info($username);
|
$user = get_user_info($username);
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
|
writelog("Failed to find user!", $username);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
_set_current_user($username, (bool) $user['isadmin']);
|
_set_current_user($username, $user['id'], (bool) $do_local_auth, (bool) $user['isadmin']);
|
||||||
|
|
||||||
if (session_id()) {
|
if (session_id()) {
|
||||||
session_unset();
|
session_unset();
|
||||||
|
@ -183,6 +189,8 @@ function _try_login($username, $password) {
|
||||||
session_regenerate_id(true) or die('session failure: regenerated id failed');
|
session_regenerate_id(true) or die('session failure: regenerated id failed');
|
||||||
session_unset();
|
session_unset();
|
||||||
$_SESSION['username'] = $username;
|
$_SESSION['username'] = $username;
|
||||||
|
$_SESSION['localauth'] = $do_local_auth;
|
||||||
|
$_SESSION['userid'] = $user['id'];
|
||||||
|
|
||||||
# requires session:
|
# requires session:
|
||||||
_check_csrf_token($user);
|
_check_csrf_token($user);
|
||||||
|
@ -202,7 +210,7 @@ function _check_session() {
|
||||||
and $_POST['adminapikey'] === $adminapikey)
|
and $_POST['adminapikey'] === $adminapikey)
|
||||||
{
|
{
|
||||||
# Allow this request, fake that we're logged in as user.
|
# Allow this request, fake that we're logged in as user.
|
||||||
return _set_current_user('admin', true, true, true);
|
return _set_current_user('admin', 1, false, true, true, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -218,7 +226,7 @@ function _check_session() {
|
||||||
session_destroy();
|
session_destroy();
|
||||||
session_unset();
|
session_unset();
|
||||||
} else {
|
} else {
|
||||||
_set_current_user($_SESSION['username'], (bool) $user['isadmin']);
|
_set_current_user($_SESSION['username'], $_SESSION['userid'], (bool) $_SESSION['localauth'], (bool) $user['isadmin']);
|
||||||
_check_csrf_token($user);
|
_check_csrf_token($user);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -277,6 +285,16 @@ function get_sess_user() {
|
||||||
return $current_user ? $current_user['username'] : null;
|
return $current_user ? $current_user['username'] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_sess_userid() {
|
||||||
|
global $current_user;
|
||||||
|
return $current_user ? $current_user['id'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function has_local_auth() {
|
||||||
|
global $current_user;
|
||||||
|
return $current_user ? $current_user['localauth'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
@session_destroy();
|
@session_destroy();
|
||||||
@session_unset();
|
@session_unset();
|
||||||
|
|
235
index.php
235
index.php
|
@ -6,6 +6,12 @@ include_once('includes/misc.inc.php');
|
||||||
|
|
||||||
global $errormsg, $blocklogin;
|
global $errormsg, $blocklogin;
|
||||||
|
|
||||||
|
$docroot = $_SERVER['DOCUMENT_ROOT'];
|
||||||
|
if (preg_match("@$docroot@", $authdb) == 1) {
|
||||||
|
$blocklogin = TRUE;
|
||||||
|
$errormsg = "You authdb is in your document root and probably downloadable. Please move it to a safe location!";
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($_GET['logout']) or isset($_POST['logout'])) {
|
if (isset($_GET['logout']) or isset($_POST['logout'])) {
|
||||||
logout();
|
logout();
|
||||||
header("Location: index.php");
|
header("Location: index.php");
|
||||||
|
@ -20,7 +26,7 @@ if (!is_logged_in() and isset($_POST['formname']) and $_POST['formname'] === "lo
|
||||||
|
|
||||||
if (is_logged_in() and isset($_POST['formname']) and $_POST['formname'] === "changepwform") {
|
if (is_logged_in() and isset($_POST['formname']) and $_POST['formname'] === "changepwform") {
|
||||||
if (get_sess_user() == $_POST['username']) {
|
if (get_sess_user() == $_POST['username']) {
|
||||||
if (!update_user(get_sess_user(), is_adminuser(), $_POST['password'])) {
|
if (!update_user(get_sess_userid(), is_adminuser(), $_POST['password'])) {
|
||||||
$errormsg = "Unable to update password!\n";
|
$errormsg = "Unable to update password!\n";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -114,7 +120,45 @@ if ($blocklogin === TRUE) {
|
||||||
<div id="dnssecinfo">
|
<div id="dnssecinfo">
|
||||||
</div>
|
</div>
|
||||||
<div id="clearlogs" style="display: none;">
|
<div id="clearlogs" style="display: none;">
|
||||||
Are you sure you want to clear all the logs? Maybe save them first?
|
Are you sure you want to clear the current logs? Maybe download them
|
||||||
|
first<?php if($allowrotatelogs) { ?>, or use "Rotate logs" to save
|
||||||
|
them on the server<?php } ?>?
|
||||||
|
</div>
|
||||||
|
<div id="rotatelogs" style="display: none;">
|
||||||
|
Are you sure you want to rotate the current logs?
|
||||||
|
</div>
|
||||||
|
<div id="searchlogs" style="display: none; text-align: right;">
|
||||||
|
<table border="0">
|
||||||
|
<tr><td>User:</td><td><input type="text" id ="searchlogs-user"><br></td></tr>
|
||||||
|
<tr><td>Log Entry:</td><td><input type="text" id ="searchlogs-entry"></td></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div id="searchzone" style="display: none; text-align: right;">
|
||||||
|
<table border="0">
|
||||||
|
<tr><td>Label:</td><td><input type="text" id ="searchzone-label"><br></td></tr>
|
||||||
|
<tr><td>Type:</td><td style="text-align: left;"><select id="searchzone-type">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="A">A</option>
|
||||||
|
<option value="AAAA">AAAA</option>
|
||||||
|
<option value="CERT">CERT</option>
|
||||||
|
<option value="CNAME">CNAME</option>
|
||||||
|
<option value="ALIAS">ALIAS</option>
|
||||||
|
<option value="LOC">LOC</option>
|
||||||
|
<option value="MX">MX</option>
|
||||||
|
<option value="NAPTR">NAPTR</option>
|
||||||
|
<option value="NS">NS</option>
|
||||||
|
<option value="PTR">PTR</option>
|
||||||
|
<option value="SOA">SOA</option>
|
||||||
|
<option value="SPF">SPF</option>
|
||||||
|
<option value="SRV">SRV</option>
|
||||||
|
<option value="SSHFP">SSHFP</option>
|
||||||
|
<option value="TLSA">TLSA</option>
|
||||||
|
<option value="CAA">CAA</option>
|
||||||
|
<option value="TXT">TXT</option>
|
||||||
|
<option value="SMIMEA">SMIMEA</option>
|
||||||
|
</select><br></td></tr>
|
||||||
|
<tr><td>Content:</td><td><input type="text" id ="searchzone-content"></td></tr>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div id="menu" class="jtable-main-container <?php if ($menutype === 'horizontal') { ?>horizontal<?php } ?>">
|
<div id="menu" class="jtable-main-container <?php if ($menutype === 'horizontal') { ?>horizontal<?php } ?>">
|
||||||
<div class="jtable-title menu-title">
|
<div class="jtable-title menu-title">
|
||||||
|
@ -137,9 +181,11 @@ if ($blocklogin === TRUE) {
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<div id="zones">
|
<div id="zones">
|
||||||
<?php if (is_adminuser() or $allowzoneadd === TRUE) { ?>
|
<?php if ($allowzoneadd === TRUE) { ?>
|
||||||
<div style="visibility: hidden;" id="ImportZone"></div>
|
<div style="display: none;" id="ImportZone"></div>
|
||||||
<div style="visibility: hidden;" id="CloneZone"></div>
|
<?php } ?>
|
||||||
|
<?php if (is_adminuser()) { ?>
|
||||||
|
<div style="display: none;" id="CloneZone"></div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<div class="tables" id="MasterZones">
|
<div class="tables" id="MasterZones">
|
||||||
<div class="searchbar" id="searchbar">
|
<div class="searchbar" id="searchbar">
|
||||||
|
@ -154,9 +200,25 @@ if ($blocklogin === TRUE) {
|
||||||
</div>
|
</div>
|
||||||
<div id="logs">
|
<div id="logs">
|
||||||
<div class="tables" id="Logs"></div>
|
<div class="tables" id="Logs"></div>
|
||||||
|
<?php if($allowrotatelogs) { ?>
|
||||||
|
<br>Log entries being viewed:
|
||||||
|
<select id="logfile">
|
||||||
|
<option value="">(Current logs)</option>
|
||||||
|
<?php
|
||||||
|
$logfiles=listrotatedlogs();
|
||||||
|
if($logfiles !== FALSE) {
|
||||||
|
foreach ($logfiles as $filename) {
|
||||||
|
echo '<option value="' . $filename . '">' . str_replace(".json","",$filename) . "</option>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?></select>
|
||||||
|
<?php } else { ?>
|
||||||
|
<input type="hidden" id="logfile" value="">
|
||||||
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
|
<?php if (has_local_auth()) { ?>
|
||||||
<div id="AboutMe">
|
<div id="AboutMe">
|
||||||
<div class="tables">
|
<div class="tables">
|
||||||
<p>Hi <?php echo get_sess_user(); ?>. You can change your password here.</p>
|
<p>Hi <?php echo get_sess_user(); ?>. You can change your password here.</p>
|
||||||
|
@ -181,9 +243,11 @@ if ($blocklogin === TRUE) {
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<input type="hidden" name="formname" value="changepwform">
|
<input type="hidden" name="formname" value="changepwform">
|
||||||
|
<input type="hidden" name="id" value="<?php echo get_sess_userid(); ?>">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.csrf_token = '<?php echo CSRF_TOKEN ?>';
|
window.csrf_token = '<?php echo CSRF_TOKEN ?>';
|
||||||
|
@ -441,7 +505,7 @@ $(document).ready(function () {
|
||||||
hoverAnimationDuration: 60,
|
hoverAnimationDuration: 60,
|
||||||
hoverAnimationEasing: undefined,
|
hoverAnimationEasing: undefined,
|
||||||
items: [
|
items: [
|
||||||
<?php if (is_adminuser() or $allowzoneadd === TRUE) { ?>
|
<?php if ($allowzoneadd === TRUE) { ?>
|
||||||
{
|
{
|
||||||
icon: 'jtable/lib/themes/metro/add.png',
|
icon: 'jtable/lib/themes/metro/add.png',
|
||||||
text: 'Import a new zone',
|
text: 'Import a new zone',
|
||||||
|
@ -449,6 +513,8 @@ $(document).ready(function () {
|
||||||
$('#ImportZone').jtable('showCreateForm');
|
$('#ImportZone').jtable('showCreateForm');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<?php } ?>
|
||||||
|
<?php if (is_adminuser()) { ?>
|
||||||
{
|
{
|
||||||
icon: 'jtable/lib/themes/metro/add.png',
|
icon: 'jtable/lib/themes/metro/add.png',
|
||||||
text: 'Clone a zone',
|
text: 'Clone a zone',
|
||||||
|
@ -473,6 +539,40 @@ $(document).ready(function () {
|
||||||
addNewRecord: 'Add to ' + zone.name,
|
addNewRecord: 'Add to ' + zone.name,
|
||||||
noDataAvailable: 'No records for ' + zone.name
|
noDataAvailable: 'No records for ' + zone.name
|
||||||
},
|
},
|
||||||
|
toolbar: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Search zone',
|
||||||
|
click: function() {
|
||||||
|
$("#searchzone").dialog({
|
||||||
|
modal: true,
|
||||||
|
title: "Search zone for ...",
|
||||||
|
width: 'auto',
|
||||||
|
buttons: {
|
||||||
|
Search: function() {
|
||||||
|
$( this ).dialog( 'close' );
|
||||||
|
opentable.find('.jtable-title-text').text(opentableTitle + " (filtered)");
|
||||||
|
opentable.jtable('load', {
|
||||||
|
label: $('#searchzone-label').val(),
|
||||||
|
type: $('#searchzone-type').val(),
|
||||||
|
content: $('#searchzone-content').val()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Reset: function() {
|
||||||
|
$('#searchzone-label').val('');
|
||||||
|
$('#searchzone-type').val('');
|
||||||
|
$('#searchzone-content').val('');
|
||||||
|
$( this ).dialog( 'close' );
|
||||||
|
opentable.find('.jtable-title-text').text(opentableTitle);
|
||||||
|
opentable.jtable('load');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
paging: true,
|
paging: true,
|
||||||
sorting: true,
|
sorting: true,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
|
@ -526,12 +626,17 @@ $(document).ready(function () {
|
||||||
'AAAA': 'AAAA',
|
'AAAA': 'AAAA',
|
||||||
'CERT': 'CERT',
|
'CERT': 'CERT',
|
||||||
'CNAME': 'CNAME',
|
'CNAME': 'CNAME',
|
||||||
|
'ALIAS': 'ALIAS',
|
||||||
'LOC': 'LOC',
|
'LOC': 'LOC',
|
||||||
'NAPTR': 'NAPTR',
|
'NAPTR': 'NAPTR',
|
||||||
'SPF': 'SPF',
|
'SPF': 'SPF',
|
||||||
'SRV': 'SRV',
|
'SRV': 'SRV',
|
||||||
'SSHFP': 'SSHFP',
|
'SSHFP': 'SSHFP',
|
||||||
'TLSA': 'TLSA',
|
'TLSA': 'TLSA',
|
||||||
|
'CAA': 'CAA',
|
||||||
|
'DNAME': 'DNAME',
|
||||||
|
'DS': 'DS',
|
||||||
|
'SMIMEA': 'SMIMEA'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -539,6 +644,9 @@ $(document).ready(function () {
|
||||||
'AAAA': 'AAAA',
|
'AAAA': 'AAAA',
|
||||||
'CERT': 'CERT',
|
'CERT': 'CERT',
|
||||||
'CNAME': 'CNAME',
|
'CNAME': 'CNAME',
|
||||||
|
'DNAME': 'DNAME',
|
||||||
|
'ALIAS': 'ALIAS',
|
||||||
|
'DS': 'DS',
|
||||||
'LOC': 'LOC',
|
'LOC': 'LOC',
|
||||||
'MX': 'MX',
|
'MX': 'MX',
|
||||||
'NAPTR': 'NAPTR',
|
'NAPTR': 'NAPTR',
|
||||||
|
@ -549,7 +657,9 @@ $(document).ready(function () {
|
||||||
'SRV': 'SRV',
|
'SRV': 'SRV',
|
||||||
'SSHFP': 'SSHFP',
|
'SSHFP': 'SSHFP',
|
||||||
'TLSA': 'TLSA',
|
'TLSA': 'TLSA',
|
||||||
|
'CAA': 'CAA',
|
||||||
'TXT': 'TXT',
|
'TXT': 'TXT',
|
||||||
|
'SMIMEA': 'SMIMEA'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
display: displayContent('type'),
|
display: displayContent('type'),
|
||||||
|
@ -609,6 +719,8 @@ $(document).ready(function () {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}, function (data) {
|
}, function (data) {
|
||||||
|
opentable=data.childTable;
|
||||||
|
opentableTitle=opentable.find('.jtable-title-text').text();
|
||||||
data.childTable.jtable('load');
|
data.childTable.jtable('load');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -758,7 +870,7 @@ $(document).ready(function () {
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
values: {'0': 'No', '1': 'Yes'},
|
values: {'0': 'No', '1': 'Yes'},
|
||||||
defaultValue: 1,
|
defaultValue: 1,
|
||||||
inputClass: 'overwrite_namerserver'
|
inputClass: 'overwrite_nameserver'
|
||||||
},
|
},
|
||||||
nameserver: {
|
nameserver: {
|
||||||
title: 'Nameservers',
|
title: 'Nameservers',
|
||||||
|
@ -779,7 +891,6 @@ $(document).ready(function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#CloneZone').jtable({
|
$('#CloneZone').jtable({
|
||||||
title: 'Clone zone',
|
title: 'Clone zone',
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -854,18 +965,18 @@ $(document).ready(function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
<?php if (is_adminuser()) { ?>
|
<?php if (is_adminuser()) { ?>
|
||||||
$('#Logs').hide();
|
$('#logs').hide();
|
||||||
$('#Users').hide();
|
$('#Users').hide();
|
||||||
$('#AboutMe').hide();
|
$('#AboutMe').hide();
|
||||||
$('#aboutme').click(function () {
|
$('#aboutme').click(function () {
|
||||||
$('#Logs').hide();
|
$('#logs').hide();
|
||||||
$('#Users').hide();
|
$('#Users').hide();
|
||||||
$('#MasterZones').hide();
|
$('#MasterZones').hide();
|
||||||
$('#SlaveZones').hide();
|
$('#SlaveZones').hide();
|
||||||
$('#AboutMe').show();
|
$('#AboutMe').show();
|
||||||
});
|
});
|
||||||
$('#useradmin').click(function () {
|
$('#useradmin').click(function () {
|
||||||
$('#Logs').hide();
|
$('#logs').hide();
|
||||||
$('#MasterZones').hide();
|
$('#MasterZones').hide();
|
||||||
$('#SlaveZones').hide();
|
$('#SlaveZones').hide();
|
||||||
$('#AboutMe').hide();
|
$('#AboutMe').hide();
|
||||||
|
@ -873,7 +984,7 @@ $(document).ready(function () {
|
||||||
$('#Users').show();
|
$('#Users').show();
|
||||||
});
|
});
|
||||||
$('#zoneadmin').click(function () {
|
$('#zoneadmin').click(function () {
|
||||||
$('#Logs').hide();
|
$('#logs').hide();
|
||||||
$('#Users').hide();
|
$('#Users').hide();
|
||||||
$('#AboutMe').hide();
|
$('#AboutMe').hide();
|
||||||
$('#MasterZones').show();
|
$('#MasterZones').show();
|
||||||
|
@ -884,8 +995,10 @@ $(document).ready(function () {
|
||||||
$('#AboutMe').hide();
|
$('#AboutMe').hide();
|
||||||
$('#MasterZones').hide();
|
$('#MasterZones').hide();
|
||||||
$('#SlaveZones').hide();
|
$('#SlaveZones').hide();
|
||||||
$('#Logs').jtable('load');
|
$('#Logs').jtable('load', {
|
||||||
$('#Logs').show();
|
logfile: $('#logfile').val()
|
||||||
|
});
|
||||||
|
$('#logs').show();
|
||||||
});
|
});
|
||||||
$('#Users').jtable({
|
$('#Users').jtable({
|
||||||
title: 'Users',
|
title: 'Users',
|
||||||
|
@ -903,11 +1016,15 @@ $(document).ready(function () {
|
||||||
deleteConfirmation: 'This user will be deleted. Are you sure?'
|
deleteConfirmation: 'This user will be deleted. Are you sure?'
|
||||||
},
|
},
|
||||||
fields: {
|
fields: {
|
||||||
|
id: {
|
||||||
|
key: true,
|
||||||
|
type: 'hidden'
|
||||||
|
},
|
||||||
emailaddress: {
|
emailaddress: {
|
||||||
title: 'User',
|
title: 'User',
|
||||||
key: true,
|
|
||||||
display: displayContent('emailaddress'),
|
display: displayContent('emailaddress'),
|
||||||
inputClass: 'emailaddress',
|
inputClass: 'emailaddress',
|
||||||
|
edit: false,
|
||||||
listClass: 'emailaddress'
|
listClass: 'emailaddress'
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
|
@ -937,8 +1054,7 @@ $(document).ready(function () {
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
sorting: false,
|
sorting: false,
|
||||||
actions: {
|
actions: {
|
||||||
listAction: 'logs.php?action=list',
|
listAction: 'logs.php?action=list'
|
||||||
deleteAction: 'logs.php?action=delete',
|
|
||||||
},
|
},
|
||||||
messages: {
|
messages: {
|
||||||
deleteConfirmation: 'This entry will be deleted. Are you sure?'
|
deleteConfirmation: 'This entry will be deleted. Are you sure?'
|
||||||
|
@ -948,6 +1064,62 @@ $(document).ready(function () {
|
||||||
hoverAnimationDuration: 60,
|
hoverAnimationDuration: 60,
|
||||||
hoverAnimationEasing: undefined,
|
hoverAnimationEasing: undefined,
|
||||||
items: [
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Search logs',
|
||||||
|
click: function() {
|
||||||
|
$("#searchlogs").dialog({
|
||||||
|
modal: true,
|
||||||
|
title: "Search logs for ...",
|
||||||
|
width: 'auto',
|
||||||
|
buttons: {
|
||||||
|
Search: function() {
|
||||||
|
$( this ).dialog( 'close' );
|
||||||
|
$('#Logs').find('.jtable-title-text').text('Logs (filtered)');
|
||||||
|
$('#Logs').jtable('load', {
|
||||||
|
logfile: $('#logfile').val(),
|
||||||
|
user: $('#searchlogs-user').val(),
|
||||||
|
entry: $('#searchlogs-entry').val()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Reset: function() {
|
||||||
|
$('#searchlogs-user').val('');
|
||||||
|
$('#searchlogs-entry').val('');
|
||||||
|
$( this ).dialog( 'close' );
|
||||||
|
$('#Logs').find('.jtable-title-text').text('Logs');
|
||||||
|
$('#Logs').jtable('load', {
|
||||||
|
logfile: $('#logfile').val()
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
<?php if($allowrotatelogs === TRUE) { ?>
|
||||||
|
{
|
||||||
|
text: 'Rotate logs',
|
||||||
|
click: function() {
|
||||||
|
$("#rotatelogs").dialog({
|
||||||
|
modal: true,
|
||||||
|
title: "Rotate logs",
|
||||||
|
width: 'auto',
|
||||||
|
buttons: {
|
||||||
|
Ok: function() {
|
||||||
|
$.get("logs.php?action=rotate");
|
||||||
|
$( this ).dialog( "close" );
|
||||||
|
$('#logfile').val('');
|
||||||
|
$('#Logs').jtable('load');
|
||||||
|
},
|
||||||
|
Cancel: function() {
|
||||||
|
$( this ).dialog( "close" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
<?php } ?>
|
||||||
|
<?php if($allowclearlogs === TRUE) { ?>
|
||||||
{
|
{
|
||||||
icon: 'img/delete_inverted.png',
|
icon: 'img/delete_inverted.png',
|
||||||
text: 'Clear logs',
|
text: 'Clear logs',
|
||||||
|
@ -960,6 +1132,7 @@ $(document).ready(function () {
|
||||||
Ok: function() {
|
Ok: function() {
|
||||||
$.get("logs.php?action=clear");
|
$.get("logs.php?action=clear");
|
||||||
$( this ).dialog( "close" );
|
$( this ).dialog( "close" );
|
||||||
|
$('#logfile').val('');
|
||||||
$('#Logs').jtable('load');
|
$('#Logs').jtable('load');
|
||||||
},
|
},
|
||||||
Cancel: function() {
|
Cancel: function() {
|
||||||
|
@ -970,17 +1143,18 @@ $(document).ready(function () {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<?php } ?>
|
||||||
{
|
{
|
||||||
icon: 'img/export.png',
|
icon: 'img/export.png',
|
||||||
text: 'Save logs',
|
text: 'Download logs',
|
||||||
click: function () {
|
click: function () {
|
||||||
var $zexport = $.get("logs.php?action=export", function(data) {
|
var $zexport = $.get("logs.php?action=export&logfile=" + $('#logfile').val(), function(data) {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
blob = new Blob([data], { type: 'text/plain' });
|
blob = new Blob([data], { type: 'text/plain' });
|
||||||
var dl = document.createElement('a');
|
var dl = document.createElement('a');
|
||||||
dl.addEventListener('click', function(ev) {
|
dl.addEventListener('click', function(ev) {
|
||||||
dl.href = URL.createObjectURL(blob);
|
dl.href = URL.createObjectURL(blob);
|
||||||
dl.download = 'nseditlogs.txt';
|
dl.download = $('#logfile').val() == "" ? 'nseditlogs.txt':$('#logfile').val() + ".txt";
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
if (document.createEvent) {
|
if (document.createEvent) {
|
||||||
|
@ -1016,6 +1190,27 @@ $(document).ready(function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#logfile').change(function () {
|
||||||
|
$('#Logs').jtable('load', {
|
||||||
|
logfile: $('#logfile').val(),
|
||||||
|
user: $('#searchlogs-user').val(),
|
||||||
|
entry: $('#searchlogs-entry').val()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
<?php } else { ?>
|
||||||
|
$('#AboutMe').hide();
|
||||||
|
$('#aboutme').click(function () {
|
||||||
|
$('#MasterZones').hide();
|
||||||
|
$('#SlaveZones').hide();
|
||||||
|
$('#AboutMe').show();
|
||||||
|
});
|
||||||
|
$('#zoneadmin').click(function () {
|
||||||
|
$('#AboutMe').hide();
|
||||||
|
$('#MasterZones').show();
|
||||||
|
$('#SlaveZones').show();
|
||||||
|
});
|
||||||
|
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
$('#MasterZones').jtable('load');
|
$('#MasterZones').jtable('load');
|
||||||
$('#SlaveZones').jtable('load');
|
$('#SlaveZones').jtable('load');
|
||||||
|
|
93
logs.php
93
logs.php
|
@ -20,32 +20,77 @@ if (!isset($_GET['action'])) {
|
||||||
jtable_respond(null, 'error', 'No action given');
|
jtable_respond(null, 'error', 'No action given');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($_GET['action']) {
|
if ($logging !== TRUE) {
|
||||||
|
jtable_respond(null, 'error', 'Logging is disabled');
|
||||||
|
} else {
|
||||||
|
switch ($_GET['action']) {
|
||||||
|
|
||||||
|
case "list":
|
||||||
|
if(!empty($_POST['logfile'])) {
|
||||||
|
if(preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{6}\.json/',$_POST['logfile']) == 1) {
|
||||||
|
$entries=json_decode(file_get_contents($logsdirectory . "/" . $_POST['logfile']),true);
|
||||||
|
} else {
|
||||||
|
jtable_respond(null, 'error', "Can't find log file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$entries=getlogs();
|
||||||
|
}
|
||||||
|
|
||||||
case "list":
|
if(!empty($_POST['user'])) {
|
||||||
global $logging;
|
$entries=array_filter($entries,
|
||||||
if ($logging !== TRUE)
|
function ($val) {
|
||||||
jtable_respond(null, 'error', 'Logging is disabled');
|
return(stripos($val['user'], $_POST['user']) !== FALSE);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
jtable_respond(getlogs());
|
if(!empty($_POST['entry'])) {
|
||||||
break;
|
$entries=array_filter($entries,
|
||||||
|
function ($val) {
|
||||||
|
return(stripos($val['log'], $_POST['entry']) !== FALSE);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
case "delete":
|
jtable_respond($entries);
|
||||||
if ($emailaddress != '' and delete_user($emailaddress) !== FALSE) {
|
break;
|
||||||
jtable_respond(null, 'delete');
|
|
||||||
} else {
|
case "export":
|
||||||
jtable_respond(null, 'error', 'Could not delete user');
|
if(!empty($_GET['logfile'])) {
|
||||||
|
if(preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{6}\.json/',$_GET['logfile']) == 1) {
|
||||||
|
$entries=json_decode(file_get_contents($logsdirectory . "/" . $_GET['logfile']),true);
|
||||||
|
} else {
|
||||||
|
jtable_respond(null, 'error', "Can't find log file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$entries=getlogs();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined('JSON_PRETTY_PRINT')) {
|
||||||
|
print json_encode($entries,JSON_PRETTY_PRINT);
|
||||||
|
} else {
|
||||||
|
print json_encode($entries);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "clear":
|
||||||
|
if($allowclearlogs === TRUE) {
|
||||||
|
clearlogs();
|
||||||
|
} else {
|
||||||
|
jtable_respond(null, 'error', 'Invalid action');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "rotate":
|
||||||
|
if($allowrotatelogs === TRUE) {
|
||||||
|
rotatelogs();
|
||||||
|
} else {
|
||||||
|
jtable_respond(null, 'error', 'Invalid action');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jtable_respond(null, 'error', 'Invalid action');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case "export":
|
|
||||||
print json_encode(getlogs());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "clear":
|
|
||||||
clearlogs();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
jtable_respond(null, 'error', 'Invalid action');
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
16
rotate-logs.php
Normal file
16
rotate-logs.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
include_once('includes/config.inc.php');
|
||||||
|
include_once('includes/session.inc.php');
|
||||||
|
include_once('includes/misc.inc.php');
|
||||||
|
|
||||||
|
if(php_sapi_name() !== 'cli') {
|
||||||
|
echo "This script is intended to be run from the command line";
|
||||||
|
} else {
|
||||||
|
if($allowrotatelogs === TRUE) {
|
||||||
|
$current_user['username']='<system>';
|
||||||
|
rotatelogs();
|
||||||
|
} else {
|
||||||
|
echo "Rotating logs has been disabled."
|
||||||
|
}
|
||||||
|
}
|
28
templates.d/template.json.example
Normal file
28
templates.d/template.json.example
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "Example Template",
|
||||||
|
"owner": "public",
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "NS",
|
||||||
|
"content": "ns1.example.com.",
|
||||||
|
"label": "ns1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "NS",
|
||||||
|
"content": "ns2.example.com.",
|
||||||
|
"label": "ns2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "example-txt",
|
||||||
|
"type": "TXT",
|
||||||
|
"content": "This is an example txt record"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "localhost",
|
||||||
|
"type": "A",
|
||||||
|
"content": "127.0.0.1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
17
users.php
17
users.php
|
@ -64,20 +64,13 @@ case "create":
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "update":
|
case "update":
|
||||||
|
$id = isset($_POST['id']) ? intval($_POST['id']) : '';
|
||||||
$emailaddress = isset($_POST['emailaddress']) ? $_POST['emailaddress'] : '';
|
$emailaddress = isset($_POST['emailaddress']) ? $_POST['emailaddress'] : '';
|
||||||
$isadmin = isset($_POST['isadmin']) ? $_POST['isadmin'] : '0';
|
$isadmin = isset($_POST['isadmin']) ? $_POST['isadmin'] : '0';
|
||||||
$password = isset($_POST['password']) ? $_POST['password'] : '';
|
$password = isset($_POST['password']) ? $_POST['password'] : '';
|
||||||
|
|
||||||
if (!valid_user($emailaddress)) {
|
if ($id != '' and update_user($id, $isadmin, $password)) {
|
||||||
jtable_respond(null, 'error', "Please only use ^[a-z0-9@_.-]+$ for usernames");
|
$result = array('isadmin' => $isadmin);
|
||||||
}
|
|
||||||
|
|
||||||
if (!user_exists($emailaddress)) {
|
|
||||||
jtable_respond(null, 'error', 'Cannot update not existing user');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (update_user($emailaddress, $isadmin, $password)) {
|
|
||||||
$result = array('emailaddress' => $emailaddress, 'isadmin' => $isadmin);
|
|
||||||
jtable_respond($result, 'single');
|
jtable_respond($result, 'single');
|
||||||
} else {
|
} else {
|
||||||
jtable_respond(null, 'error', 'Could not update user');
|
jtable_respond(null, 'error', 'Could not update user');
|
||||||
|
@ -85,7 +78,9 @@ case "update":
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "delete":
|
case "delete":
|
||||||
if ($emailaddress != '' and delete_user($emailaddress) !== FALSE) {
|
$id = isset($_POST['id']) ? intval($_POST['id']) : '';
|
||||||
|
|
||||||
|
if ($id != '' and delete_user($id) !== FALSE) {
|
||||||
jtable_respond(null, 'delete');
|
jtable_respond(null, 'delete');
|
||||||
} else {
|
} else {
|
||||||
jtable_respond(null, 'error', 'Could not delete user');
|
jtable_respond(null, 'error', 'Could not delete user');
|
||||||
|
|
101
zones.php
101
zones.php
|
@ -12,10 +12,12 @@ if (!is_csrf_safe()) {
|
||||||
jtable_respond(null, 'error', "Authentication required");
|
jtable_respond(null, 'error', "Authentication required");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$quoteus = array('TXT', 'SPF');
|
||||||
|
|
||||||
/* This function is taken from:
|
/* This function is taken from:
|
||||||
http://pageconfig.com/post/how-to-validate-ascii-text-in-php and got fixed by
|
http://pageconfig.com/post/how-to-validate-ascii-text-in-php and got fixed by
|
||||||
#powerdns */
|
#powerdns */
|
||||||
|
|
||||||
function is_ascii($string) {
|
function is_ascii($string) {
|
||||||
return ( bool ) ! preg_match( '/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x80-\\xff]/' , $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(1, $zonename, SQLITE3_TEXT);
|
||||||
$q->bindValue(2, $accountname, SQLITE3_TEXT);
|
$q->bindValue(2, $accountname, SQLITE3_TEXT);
|
||||||
$q->execute();
|
$q->execute();
|
||||||
$db->close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function delete_db_zone($zonename) {
|
function delete_db_zone($zonename) {
|
||||||
|
@ -123,7 +124,6 @@ function delete_db_zone($zonename) {
|
||||||
$q = $db->prepare("DELETE FROM zones WHERE zone = ?");
|
$q = $db->prepare("DELETE FROM zones WHERE zone = ?");
|
||||||
$q->bindValue(1, $zonename, SQLITE3_TEXT);
|
$q->bindValue(1, $zonename, SQLITE3_TEXT);
|
||||||
$q->execute();
|
$q->execute();
|
||||||
$db->close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_zone_account($zonename, $default) {
|
function get_zone_account($zonename, $default) {
|
||||||
|
@ -135,7 +135,6 @@ function get_zone_account($zonename, $default) {
|
||||||
$q->bindValue(1, $zonename, SQLITE3_TEXT);
|
$q->bindValue(1, $zonename, SQLITE3_TEXT);
|
||||||
$result = $q->execute();
|
$result = $q->execute();
|
||||||
$zoneinfo = $result->fetchArray(SQLITE3_ASSOC);
|
$zoneinfo = $result->fetchArray(SQLITE3_ASSOC);
|
||||||
$db->close();
|
|
||||||
if (isset($zoneinfo['emailaddress']) && $zoneinfo['emailaddress'] != null ) {
|
if (isset($zoneinfo['emailaddress']) && $zoneinfo['emailaddress'] != null ) {
|
||||||
return $zoneinfo['emailaddress'];
|
return $zoneinfo['emailaddress'];
|
||||||
}
|
}
|
||||||
|
@ -143,6 +142,16 @@ function get_zone_account($zonename, $default) {
|
||||||
return $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) {
|
function check_account($zone) {
|
||||||
return is_adminuser() or ($zone->account === get_sess_user());
|
return is_adminuser() or ($zone->account === get_sess_user());
|
||||||
}
|
}
|
||||||
|
@ -165,7 +174,9 @@ case "listslaves":
|
||||||
foreach ($api->listzones($q) as $sresult) {
|
foreach ($api->listzones($q) as $sresult) {
|
||||||
$zone = new Zone();
|
$zone = new Zone();
|
||||||
$zone->parse($sresult);
|
$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))
|
if (!check_account($zone))
|
||||||
continue;
|
continue;
|
||||||
|
@ -188,6 +199,31 @@ case "listrecords":
|
||||||
$zone = new Zone();
|
$zone = new Zone();
|
||||||
$zone->parse($zonedata);
|
$zone->parse($zonedata);
|
||||||
$records = $zone->rrsets2records();
|
$records = $zone->rrsets2records();
|
||||||
|
|
||||||
|
if(!empty($_POST['label'])) {
|
||||||
|
$records=array_filter($records,
|
||||||
|
function ($val) {
|
||||||
|
return(stripos($val['name'], $_POST['label']) !== FALSE);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($_POST['type'])) {
|
||||||
|
$records=array_filter($records,
|
||||||
|
function ($val) {
|
||||||
|
return($val['type'] == $_POST['type']);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($_POST['content'])) {
|
||||||
|
$records=array_filter($records,
|
||||||
|
function ($val) {
|
||||||
|
return(stripos($val['content'], $_POST['content']) !== FALSE);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($_GET['jtSorting'])) {
|
if (isset($_GET['jtSorting'])) {
|
||||||
list($scolumn, $sorder) = preg_split("/ /", $_GET['jtSorting']);
|
list($scolumn, $sorder) = preg_split("/ /", $_GET['jtSorting']);
|
||||||
switch ($scolumn) {
|
switch ($scolumn) {
|
||||||
|
@ -248,7 +284,7 @@ case "create":
|
||||||
$zone->importData($_POST['zone']);
|
$zone->importData($_POST['zone']);
|
||||||
}
|
}
|
||||||
if (isset($defaults['soa_edit_api'])) {
|
if (isset($defaults['soa_edit_api'])) {
|
||||||
$zone->setSoaEditApi($defaults['soa_edit_api']);
|
$zone->setSoaEditApi($defaults['soa_edit_api'], True);
|
||||||
}
|
}
|
||||||
if (isset($defaults['soa_edit'])) {
|
if (isset($defaults['soa_edit'])) {
|
||||||
$zone->setSoaEdit($defaults['soa_edit']);
|
$zone->setSoaEdit($defaults['soa_edit']);
|
||||||
|
@ -286,7 +322,7 @@ case "create":
|
||||||
if ($template['name'] !== $_POST['template']) continue;
|
if ($template['name'] !== $_POST['template']) continue;
|
||||||
|
|
||||||
foreach ($template['records'] as $record) {
|
foreach ($template['records'] as $record) {
|
||||||
$rrset = $zone->getRRSet($record['label'], $record['type']);
|
$rrset = $zone->getRRSet($record['name'], $record['type']);
|
||||||
if ($rrset) {
|
if ($rrset) {
|
||||||
$rrset->delete();
|
$rrset->delete();
|
||||||
}
|
}
|
||||||
|
@ -294,7 +330,10 @@ case "create":
|
||||||
$api->savezone($zone->export());
|
$api->savezone($zone->export());
|
||||||
|
|
||||||
foreach ($template['records'] as $record) {
|
foreach ($template['records'] as $record) {
|
||||||
$zone->addRecord($record['name'], $record['type'], $record['content']);
|
if ($record['type'] == 'NS') continue;
|
||||||
|
$name = $record['name'] != '' ? join(Array($record['name'],'.',$zonename)) : $zonename;
|
||||||
|
$record['content'] = str_replace("[zonename]", $zonename, $record['content']);
|
||||||
|
$zone->addRecord($name, $record['type'], $record['content']);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -309,6 +348,8 @@ case "create":
|
||||||
case "update":
|
case "update":
|
||||||
$zone = new Zone();
|
$zone = new Zone();
|
||||||
$zone->parse($api->loadzone($_POST['id']));
|
$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;
|
$zoneaccount = isset($_POST['account']) ? $_POST['account'] : $zone->account;
|
||||||
|
|
||||||
if ($zone->account !== $zoneaccount) {
|
if ($zone->account !== $zoneaccount) {
|
||||||
|
@ -335,6 +376,8 @@ case "update":
|
||||||
case "createrecord":
|
case "createrecord":
|
||||||
$zone = new Zone();
|
$zone = new Zone();
|
||||||
$zone->parse($api->loadzone($_GET['zoneid']));
|
$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'] : '';
|
$name = isset($_POST['name']) ? $_POST['name'] : '';
|
||||||
$type = $_POST['type'];
|
$type = $_POST['type'];
|
||||||
|
@ -344,12 +387,13 @@ case "createrecord":
|
||||||
$name = $zone->name;
|
$name = $zone->name;
|
||||||
} elseif (string_ends_with($name, '.')) {
|
} elseif (string_ends_with($name, '.')) {
|
||||||
# "absolute" name, shouldn't append zone[name] - but check.
|
# "absolute" name, shouldn't append zone[name] - but check.
|
||||||
$name = substr($name, 0, -1);
|
|
||||||
if (!string_ends_with($name, $zone->name)) {
|
if (!string_ends_with($name, $zone->name)) {
|
||||||
jtable_respond(null, 'error', "Name $name not in zone ".$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;
|
$name = $name . '.' . $zone->name;
|
||||||
|
} else {
|
||||||
|
$name = $name.'.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_valid_label($name)) {
|
if (!_valid_label($name)) {
|
||||||
|
@ -362,6 +406,10 @@ case "createrecord":
|
||||||
jtable_respond(null, 'error', "Please only use ASCII-characters in your fields");
|
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']);
|
$record = $zone->addRecord($name, $type, $content, $_POST['disabled'], $_POST['ttl'], $_POST['setptr']);
|
||||||
$api->savezone($zone->export());
|
$api->savezone($zone->export());
|
||||||
|
|
||||||
|
@ -372,16 +420,25 @@ case "createrecord":
|
||||||
case "editrecord":
|
case "editrecord":
|
||||||
$zone = new Zone();
|
$zone = new Zone();
|
||||||
$zone->parse($api->loadzone($_GET['zoneid']));
|
$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'] : '');
|
$old_record = decode_record_id(isset($_POST['id']) ? $_POST['id'] : '');
|
||||||
|
|
||||||
$rrset = $zone->getRRSet($old_record['name'], $old_record['type']);
|
$rrset = $zone->getRRSet($old_record['name'], $old_record['type']);
|
||||||
$rrset->deleteRecord($old_record['content']);
|
$rrset->deleteRecord($old_record['content']);
|
||||||
$zone->addRecord($_POST['name'], $_POST['type'], $_POST['content'], $_POST['disabled'], $_POST['ttl'], $_POST['setptr']);
|
|
||||||
|
$content = $_POST['content'];
|
||||||
|
$type = $_POST['type'];
|
||||||
|
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());
|
$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']);
|
writelog("Updated record ".$_POST['id']." to ".$record['id']);
|
||||||
jtable_respond($record, 'single');
|
jtable_respond($record, 'single');
|
||||||
break;
|
break;
|
||||||
|
@ -389,6 +446,8 @@ case "editrecord":
|
||||||
case "deleterecord":
|
case "deleterecord":
|
||||||
$zone = new Zone();
|
$zone = new Zone();
|
||||||
$zone->parse($api->loadzone($_GET['zoneid']));
|
$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'] : '');
|
$old_record = decode_record_id(isset($_POST['id']) ? $_POST['id'] : '');
|
||||||
$rrset = $zone->getRRSet($old_record['name'], $old_record['type']);
|
$rrset = $zone->getRRSet($old_record['name'], $old_record['type']);
|
||||||
|
@ -419,10 +478,14 @@ case "clone":
|
||||||
|
|
||||||
$srczone = new Zone();
|
$srczone = new Zone();
|
||||||
$srczone->parse($api->loadzone($src));
|
$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->setId('');
|
||||||
$srczone->setName($name);
|
$srczone->setName($name);
|
||||||
$srczone->setSerial('');
|
$srczone->setSerial('');
|
||||||
|
$srczone->setKind($_POST['kind']);
|
||||||
|
|
||||||
$zone = $api->savezone($srczone->export());
|
$zone = $api->savezone($srczone->export());
|
||||||
|
|
||||||
$srczone->parse($zone);
|
$srczone->parse($zone);
|
||||||
|
@ -432,6 +495,15 @@ case "clone":
|
||||||
$newname = preg_replace('/'.$src.'$/', $name, $newname);
|
$newname = preg_replace('/'.$src.'$/', $name, $newname);
|
||||||
$rrset->setName($newname);
|
$rrset->setName($newname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_adminuser() && isset($_POST['account'])) {
|
||||||
|
add_db_zone($name, $_POST['account']);
|
||||||
|
$srczone->setAccount($_POST['account']);
|
||||||
|
} else {
|
||||||
|
add_db_zone($name, get_sess_user());
|
||||||
|
$srczone->setAccount(get_sess_user());
|
||||||
|
}
|
||||||
|
|
||||||
$zone = $api->savezone($srczone->export());
|
$zone = $api->savezone($srczone->export());
|
||||||
|
|
||||||
writelog("Cloned zone $src into $name");
|
writelog("Cloned zone $src into $name");
|
||||||
|
@ -471,8 +543,11 @@ case "getformnameservers":
|
||||||
break;
|
break;
|
||||||
case "formzonelist":
|
case "formzonelist":
|
||||||
$zones = $api->listzones();
|
$zones = $api->listzones();
|
||||||
|
usort($zones, "zone_compare");
|
||||||
$ret = array();
|
$ret = array();
|
||||||
foreach ($zones as $zone) {
|
foreach ($zones as $zone) {
|
||||||
|
if (!check_account($zone))
|
||||||
|
continue;
|
||||||
if ($zone['kind'] == 'Slave')
|
if ($zone['kind'] == 'Slave')
|
||||||
continue;
|
continue;
|
||||||
array_push($ret, array(
|
array_push($ret, array(
|
||||||
|
@ -488,4 +563,4 @@ default:
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
jtable_respond(null, 'error', $e->getMessage());
|
jtable_respond(null, 'error', $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue