Commit 9852a98c2a7918edbdc8a7860f035de556a1fa9c

Authored by Péter Szládovics
1 parent b075427b

add code

Showing 79 changed files with 7359 additions and 0 deletions
config/config.php 0 → 100644
  1 +<?php
  2 +// Include paths.
  3 +$_CONF['smbind_ng'] = "/usr/share/smbind-ng/php-ng/";
  4 +$_CONF['smarty_path'] = "/usr/share/smbind-ng/smarty/libs";
  5 +$_CONF['peardb_path'] = "/usr/share/php";
  6 +$_CONF['title'] = "";
  7 +$_CONF['footer'] = "";
  8 +$_CONF['marker'] = "";
  9 +$_CONF['template'] = "default";
  10 +$_CONF['recaptcha'] = "yes";
  11 +$_CONF['tmp_path'] = $_CONF['smbind_ng'] . "tmp";
  12 +$_CONF['rc_pubkey'] = "";
  13 +$_CONF['rc_privkey'] = "";
  14 +$_CONF['nocaptcha'] = array();
  15 +$_CONF['staticdomain'] = 'static.myonline.hu';
  16 +
  17 +// Database DSN.
  18 +$_CONF['db_type'] = 'mysql'; // mysql for MySQL, pgsql for PostgreSQL
  19 +$_CONF['db_user'] = '';
  20 +$_CONF['db_pass'] = '';
  21 +$_CONF['db_host'] = '';
  22 +$_CONF['db_db'] = '';
  23 +
  24 +// Zone data paths (normal).
  25 +$_CONF['path'] = "/etc/smbind-ng/zones/";
  26 +$_CONF['conf'] = "/etc/smbind-ng/smbind.conf"; # Include this file in named.conf.
  27 +$_CONF['rollerconf'] = "/etc/smbind-ng/rollrec/zones.rollrec";
  28 +
  29 +// BIND utilities.
  30 +$_CONF['namedcheckconf'] = "/usr/sbin/named-checkconf";
  31 +$_CONF['namedcheckzone'] = "/usr/sbin/named-checkzone";
  32 +$_CONF['rndc'] = "/usr/sbin/rndc";
  33 +$_CONF['zonesigner'] = "/usr/sbin/zonesigner";
  34 +$_CONF['rollinit'] = "/usr/sbin/rollinit";
  35 +$_CONF['dig'] = "/usr/bin/dig";
  36 +?>
... ...
index.php 0 → 100644
  1 +<?php
  2 +require_once "src/include.php";
  3 +
  4 +$smarty->assign("pagetitle", "Main");
  5 +$smarty->assign("user", $user->getFullName());
  6 +$smarty->assign("zones", sizeof($user->getMasters('live')));
  7 +$smarty->assign("slave_zones", sizeof($user->getSlaves('live')));
  8 +$smarty->assign("status", rndc_status());
  9 +$smarty->assign("bad", $user->getUnvalidatedZones('master'));
  10 +$smarty->assign("bad_slaves", $user->getUnvalidatedZones('slave'));
  11 +$smarty->assign("comm", $user->getCommitableZones('master'));
  12 +$smarty->assign("comm_slaves", $user->getCommitableZones('slave'));
  13 +$smarty->assign("del", $user->getDeletedZones('master'));
  14 +$smarty->assign("del_slaves", $user->getDeletedZones('slave'));
  15 +$smarty->assign("template", "mainpage.tpl");
  16 +$smarty->assign("help", help("mainpage"));
  17 +$smarty->assign("menu_button", menu_buttons());
  18 +$smarty->display("main.tpl");
  19 +?>
... ...
lib/punycode.class.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * The MIT License (MIT)
  4 + *
  5 + * Copyright (c) 2013 mk-j, zedwood.com
  6 + *
  7 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  8 + * of this software and associated documentation files (the "Software"), to deal
  9 + * in the Software without restriction, including without limitation the rights
  10 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 + * copies of the Software, and to permit persons to whom the Software is
  12 + * furnished to do so, subject to the following conditions:
  13 + *
  14 + * The above copyright notice and this permission notice shall be included in all
  15 + * copies or substantial portions of the Software.
  16 + *
  17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23 + * SOFTWARE.
  24 + */
  25 +function_exists('mb_internal_encoding') or die('unsupported dependency, mbstring');
  26 +class Punycode
  27 +{
  28 + const TMIN = 1;
  29 + const TMAX = 26;
  30 + const BASE = 36;
  31 + const INITIAL_N = 128;
  32 + const INITIAL_BIAS = 72;
  33 + const DAMP = 700;
  34 + const SKEW = 38;
  35 + const DELIMITER = '-';
  36 + //Punycode::::encodeHostName() corresponds to idna_toASCII('xärg.örg');
  37 + public static function encodeHostName($hostname)
  38 + {
  39 + if (!self::is_valid_utf8($hostname))
  40 + {
  41 + return $hostname;//invalid
  42 + }
  43 + if (function_exists('idn_to_ascii') && 0)
  44 + {
  45 + return idn_to_ascii($hostname);//php 5.3+
  46 + }
  47 + $old_encoding = mb_internal_encoding();
  48 + mb_internal_encoding("UTF-8");
  49 + $pieces = explode(".", self::mb_strtolower($hostname) );
  50 + $punycode_pieces = array();
  51 + foreach($pieces as $piece)
  52 + {
  53 + if (preg_match("/[\x{80}-\x{FFFF}]/u", $piece))//is multi byte utf8
  54 + {
  55 + $punycode_pieces[] = "xn--".self::encode($piece);
  56 + }
  57 + else if (preg_match('/^[a-z\d][a-z\d-]{0,62}$/i', $piece) && !preg_match('/-$/', $piece) )//is valid ascii hostname
  58 + {
  59 + $punycode_pieces[] = $piece;
  60 + }
  61 + else
  62 + {
  63 + mb_internal_encoding($old_encoding);
  64 + return $hostname;//invalid domain
  65 + }
  66 + }
  67 + mb_internal_encoding($old_encoding);
  68 + return implode(".", $punycode_pieces);
  69 + }
  70 + //Punycode::::decodeHostName() corresponds to idna_toUnicode('xn--xrg-9ka.xn--rg-eka');
  71 + public static function decodeHostName($encoded_hostname)
  72 + {
  73 + if (!preg_match('/[a-z\d.-]{1,255}/', $encoded_hostname))
  74 + {
  75 + return false;
  76 + }
  77 + if (function_exists('idn_to_utf8') && 0)
  78 + {
  79 + return idn_to_utf8($encoded_hostname);
  80 + }
  81 + $old_encoding = mb_internal_encoding();
  82 + mb_internal_encoding("UTF-8");
  83 + $pieces = explode(".", strtolower($encoded_hostname));
  84 + foreach($pieces as $piece)
  85 + {
  86 + if (!preg_match('/^[a-z\d][a-z\d-]{0,62}$/i', $piece) || preg_match('/-$/', $piece) )
  87 + {
  88 + mb_internal_encoding($old_encoding);
  89 + return $encoded_hostname;//invalid
  90 + }
  91 + $punycode_pieces[] = strpos($piece, "xn--")===0 ? self::decode(substr($piece,4)) : $piece;
  92 + }
  93 + mb_internal_encoding($old_encoding);
  94 + return implode(".", $punycode_pieces);
  95 + }
  96 + protected static function encode($input)
  97 + {
  98 + try
  99 + {
  100 + $n = self::INITIAL_N;
  101 + $delta = 0;
  102 + $bias = self::INITIAL_BIAS;
  103 + $output='';
  104 + $input_length = self::mb_strlen($input);
  105 + $b=0;
  106 + for($i=0; $i<$input_length; $i++)
  107 + {
  108 + $chr = self::mb_substr($input,$i,1);
  109 + $c = self::uniord( $chr );//autoloaded class
  110 + if ($c < self::INITIAL_N)
  111 + {
  112 + $output.= $chr;
  113 + $b++;
  114 + }
  115 + }
  116 +
  117 + if ($b==$input_length)//no international chars to convert to punycode here
  118 + {
  119 + throw new Exception("PunycodeException.BAD_INPUT");
  120 + }
  121 + else if ($b>0)
  122 + {
  123 + $output.= self::DELIMITER;
  124 + }
  125 + $h = $b;
  126 + while($h < $input_length)
  127 + {
  128 + $m = PHP_INT_MAX;
  129 + // Find the minimum code point >= n
  130 + for($i=0; $i<$input_length; $i++)
  131 + {
  132 + $chr = self::mb_substr($input,$i,1);
  133 + $c = self::uniord( $chr );
  134 + if ($c >= $n && $c < $m)
  135 + {
  136 + $m = $c;
  137 + }
  138 + }
  139 +
  140 +
  141 + if (($m - $n) > (PHP_INT_MAX - $delta) / ($h+1))
  142 + {
  143 + throw new Exception("PunycodeException.OVERFLOW");
  144 + }
  145 + $delta = $delta + ($m - $n) * ($h + 1);
  146 + $n = $m;
  147 +
  148 + for($j=0; $j<$input_length; $j++)
  149 + {
  150 + $chr = self::mb_substr($input,$j,1);
  151 + $c = self::uniord( $chr );
  152 + if ($c < $n)
  153 + {
  154 + $delta++;
  155 + if (0==$delta)
  156 + {
  157 + throw new Exception("PunycodeException.OVERFLOW");
  158 + }
  159 + }
  160 +
  161 + if ($c == $n)
  162 + {
  163 + $q = $delta;
  164 + for($k= self::BASE;; $k+=self::BASE)
  165 + {
  166 + $t=0;
  167 + if ($k <= $bias)
  168 + {
  169 + $t= self::TMIN;
  170 + } else if ($k >= $bias + self::TMAX) {
  171 + $t= self::TMAX;
  172 + } else {
  173 + $t = $k - $bias;
  174 + }
  175 + if ($q < $t)
  176 + {
  177 + break;
  178 + }
  179 + $output.= chr( self::digit2codepoint($t + ($q - $t) % (self::BASE - $t)) );
  180 + $q = floor( ($q-$t) / (self::BASE - $t) );//integer division
  181 + }
  182 + $output.= chr( self::digit2codepoint($q) );
  183 + $bias = self::adapt($delta, $h+1, $h==$b);
  184 + $delta=0;
  185 + $h++;
  186 + }
  187 + }
  188 + $delta++;
  189 + $n++;
  190 + }
  191 + }
  192 + catch (Exception $e)
  193 + {
  194 + error_log("[PUNYCODE] error ".$e->getMessage());
  195 + return $input;
  196 + }
  197 + return $output;
  198 + }
  199 + protected static function decode($input)
  200 + {
  201 + try
  202 + {
  203 + $n = self::INITIAL_N;
  204 + $i = 0;
  205 + $bias = self::INITIAL_BIAS;
  206 + $output = '';
  207 + $d = self::rstrpos($input, self::DELIMITER);
  208 + if ($d>0) {
  209 + for($j=0; $j<$d; $j++) {
  210 + $chr = self::mb_substr($input,$j,1);
  211 + $c = self::uniord( $chr );
  212 + if ($c>=self::INITIAL_N) {
  213 + throw new Exception("PunycodeException.BAD_INPUT");
  214 + }
  215 + $output.=$chr;
  216 + }
  217 + $d++;
  218 + } else {
  219 + $d = 0;
  220 + }
  221 + $input_length = self::mb_strlen($input);
  222 + while ($d < $input_length) {
  223 + $oldi = $i;
  224 + $w = 1;
  225 + for($k= self::BASE;; $k += self::BASE) {
  226 + if ($d == $input_length) {
  227 + throw new Exception("PunycodeException.BAD_INPUT");
  228 + }
  229 + $chr = self::mb_substr($input,$d++,1);
  230 + $c = self::uniord( $chr );
  231 + $digit = self::codepoint2digit($c);
  232 + if ($digit > (PHP_INT_MAX - $i) / $w) {
  233 + throw new Exception("PunycodeException.OVERFLOW");
  234 + }
  235 + $i = $i + $digit * $w;
  236 + $t=0;
  237 + if ($k <= $bias) {
  238 + $t = self::TMIN;
  239 + } else if ($k >= $bias + self::TMAX) {
  240 + $t = self::TMAX;
  241 + } else {
  242 + $t = $k - $bias;
  243 + }
  244 + if ($digit < $t) {
  245 + break;
  246 + }
  247 + $w = $w * (self::BASE - $t);
  248 + }
  249 + $output_length = self::mb_strlen($output);
  250 + $bias = self::adapt($i - $oldi, $output_length + 1, $oldi == 0);
  251 + if ($i / ($output_length + 1) > PHP_INT_MAX - $n) {
  252 + throw new Exception("PunycodeException.OVERFLOW");
  253 + }
  254 + $n = floor($n + $i / ($output_length + 1));
  255 + $i = $i % ($output_length + 1);
  256 + $output = self::mb_strinsert($output, self::utf8($n), $i);
  257 + $i++;
  258 + }
  259 + }
  260 + catch(Exception $e)
  261 + {
  262 + error_log("[PUNYCODE] error ".$e->getMessage());
  263 + return $input;
  264 + }
  265 + return $output;
  266 + }
  267 +//adapt patched from:
  268 +//https://github.com/takezoh/php-PunycodeEncoder/blob/master/punycode.php
  269 + protected static function adapt($delta, $numpoints, $firsttime)
  270 + {
  271 + $delta = (int)($firsttime ? $delta / self::DAMP : $delta / 2);
  272 + $delta += (int)($delta / $numpoints);
  273 + $k = 0;
  274 + while ($delta > (((self::BASE - self::TMIN) * self::TMAX) / 2)) {
  275 + $delta = (int)($delta / (self::BASE - self::TMIN));
  276 + $k += self::BASE;
  277 + }
  278 + return $k + (int)((self::BASE - self::TMIN + 1) * $delta / ($delta + self::SKEW));
  279 + }
  280 + protected static function digit2codepoint($d)
  281 + {
  282 + if ($d < 26) {
  283 + // 0..25 : 'a'..'z'
  284 + return $d + ord('a');
  285 + } else if ($d < 36) {
  286 + // 26..35 : '0'..'9';
  287 + return $d - 26 + ord('0');
  288 + } else {
  289 + throw new Exception("PunycodeException.BAD_INPUT");
  290 + }
  291 + }
  292 + protected static function codepoint2digit($c)
  293 + {
  294 + if ($c - ord('0') < 10) {
  295 + // '0'..'9' : 26..35
  296 + return $c - ord('0') + 26;
  297 + } else if ($c - ord('a') < 26) {
  298 + // 'a'..'z' : 0..25
  299 + return $c - ord('a');
  300 + } else {
  301 + throw new Exception("PunycodeException.BAD_INPUT");
  302 + }
  303 + }
  304 + protected static function rstrpos($haystack, $needle)
  305 + {
  306 + $pos = strpos (strrev($haystack), $needle);
  307 + if ($pos === false)
  308 + return false;
  309 + return strlen ($haystack)-1 - $pos;
  310 + }
  311 + protected static function mb_strinsert($haystack, $needle, $position)
  312 + {
  313 + $old_encoding = mb_internal_encoding();
  314 + mb_internal_encoding("UTF-8");
  315 + $r = mb_substr($haystack,0,$position).$needle.mb_substr($haystack,$position);
  316 + mb_internal_encoding($old_encoding);
  317 + return $r;
  318 + }
  319 +
  320 + protected static function mb_substr($str,$start,$length)
  321 + {
  322 + $old_encoding = mb_internal_encoding();
  323 + mb_internal_encoding("UTF-8");
  324 + $r = mb_substr($str,$start,$length);
  325 + mb_internal_encoding($old_encoding);
  326 + return $r;
  327 + }
  328 + protected static function mb_strlen($str)
  329 + {
  330 + $old_encoding = mb_internal_encoding();
  331 + mb_internal_encoding("UTF-8");
  332 + $r = mb_strlen($str);
  333 + mb_internal_encoding($old_encoding);
  334 + return $r;
  335 + }
  336 + protected static function mb_strtolower($str)
  337 + {
  338 + $old_encoding = mb_internal_encoding();
  339 + mb_internal_encoding("UTF-8");
  340 + $r = mb_strtolower($str);
  341 + mb_internal_encoding($old_encoding);
  342 + return $r;
  343 + }
  344 +
  345 + public static function uniord($c)//cousin of ord() but for unicode
  346 + {
  347 + $ord0 = ord($c{0}); if ($ord0>=0 && $ord0<=127) return $ord0;
  348 + $ord1 = ord($c{1}); if ($ord0>=192 && $ord0<=223) return ($ord0-192)*64 + ($ord1-128);
  349 + if ($ord0==0xed && ($ord1 & 0xa0) == 0xa0) return false; //code points, 0xd800 to 0xdfff
  350 + $ord2 = ord($c{2}); if ($ord0>=224 && $ord0<=239) return ($ord0-224)*4096 + ($ord1-128)*64 + ($ord2-128);
  351 + $ord3 = ord($c{3}); if ($ord0>=240 && $ord0<=247) return ($ord0-240)*262144 + ($ord1-128)*4096 + ($ord2-128)*64 + ($ord3-128);
  352 + return false;
  353 + }
  354 + public static function utf8($num)//cousin of ascii() but for utf8
  355 + {
  356 + if($num<=0x7F) return chr($num);
  357 + if($num<=0x7FF) return chr(($num>>6)+192).chr(($num&63)+128);
  358 + if(0xd800<=$num && $num<=0xdfff) return '';//invalid block of utf8
  359 + if($num<=0xFFFF) return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
  360 + if($num<=0x10FFFF) return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128).chr(($num&63)+128);
  361 + return '';
  362 + }
  363 +
  364 + public static function is_valid_utf8($string)
  365 + {
  366 + for ($i=0, $ix=strlen($string); $i < $ix; $i++)
  367 + {
  368 + $c = ord($string{$i});
  369 + if ($c==0x09 || $c==0x0a || $c==0x0d || (0x20 <= $c && $c < 0x7e) ) $n = 0; # 0bbbbbbb
  370 + else if (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
  371 + else if ($c==0xed && (ord($string{$i+1}) & 0xa0)==0xa0) return false; //code points, 0xd800 to 0xdfff
  372 + else if (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
  373 + else if (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
  374 + //else if (($c & 0xFC) == 0xF8) $n=4; # 111110bb //byte 5, unnecessary in 4 byte UTF-8
  375 + //else if (($c & 0xFE) == 0xFC) $n=5; # 1111110b //byte 6, unnecessary in 4 byte UTF-8
  376 + else return false;
  377 + for ($j=0; $j<$n; $j++) { // n bytes matching 10bbbbbb follow ?
  378 + if ((++$i == $ix) || ((ord($string{$i}) & 0xC0) != 0x80))
  379 + return false;
  380 + }
  381 + }
  382 + return true;
  383 + }
  384 +}
  385 +
... ...
lib/recaptchalib.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * This is a PHP library that handles calling reCAPTCHA.
  4 + * - Documentation and latest version
  5 + * http://recaptcha.net/plugins/php/
  6 + * - Get a reCAPTCHA API Key
  7 + * https://www.google.com/recaptcha/admin/create
  8 + * - Discussion group
  9 + * http://groups.google.com/group/recaptcha
  10 + *
  11 + * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
  12 + * AUTHORS:
  13 + * Mike Crawford
  14 + * Ben Maurer
  15 + *
  16 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  17 + * of this software and associated documentation files (the "Software"), to deal
  18 + * in the Software without restriction, including without limitation the rights
  19 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  20 + * copies of the Software, and to permit persons to whom the Software is
  21 + * furnished to do so, subject to the following conditions:
  22 + *
  23 + * The above copyright notice and this permission notice shall be included in
  24 + * all copies or substantial portions of the Software.
  25 + *
  26 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  27 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  28 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  29 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  30 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  31 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  32 + * THE SOFTWARE.
  33 + */
  34 +
  35 +/**
  36 + * The reCAPTCHA server URL's
  37 + */
  38 +define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
  39 +define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
  40 +define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
  41 +
  42 +/**
  43 + * Encodes the given data into a query string format
  44 + * @param $data - array of string elements to be encoded
  45 + * @return string - encoded request
  46 + */
  47 +function _recaptcha_qsencode ($data) {
  48 + $req = "";
  49 + foreach ( $data as $key => $value )
  50 + $req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
  51 +
  52 + // Cut the last '&'
  53 + $req=substr($req,0,strlen($req)-1);
  54 + return $req;
  55 +}
  56 +
  57 +
  58 +
  59 +/**
  60 + * Submits an HTTP POST to a reCAPTCHA server
  61 + * @param string $host
  62 + * @param string $path
  63 + * @param array $data
  64 + * @param int port
  65 + * @return array response
  66 + */
  67 +function _recaptcha_http_post($host, $path, $data, $port = 80) {
  68 +
  69 + $req = _recaptcha_qsencode ($data);
  70 +
  71 + $http_request = "POST $path HTTP/1.0\r\n";
  72 + $http_request .= "Host: $host\r\n";
  73 + $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
  74 + $http_request .= "Content-Length: " . strlen($req) . "\r\n";
  75 + $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
  76 + $http_request .= "\r\n";
  77 + $http_request .= $req;
  78 +
  79 + $response = '';
  80 + if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
  81 + die ('Could not open socket');
  82 + }
  83 +
  84 + fwrite($fs, $http_request);
  85 +
  86 + while ( !feof($fs) )
  87 + $response .= fgets($fs, 1160); // One TCP-IP packet
  88 + fclose($fs);
  89 + $response = explode("\r\n\r\n", $response, 2);
  90 +
  91 + return $response;
  92 +}
  93 +
  94 +
  95 +
  96 +/**
  97 + * Gets the challenge HTML (javascript and non-javascript version).
  98 + * This is called from the browser, and the resulting reCAPTCHA HTML widget
  99 + * is embedded within the HTML form it was called from.
  100 + * @param string $pubkey A public key for reCAPTCHA
  101 + * @param string $error The error given by reCAPTCHA (optional, default is null)
  102 + * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
  103 +
  104 + * @return string - The HTML to be embedded in the user's form.
  105 + */
  106 +function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
  107 +{
  108 + if ($pubkey == null || $pubkey == '') {
  109 + die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
  110 + }
  111 +
  112 + if ($use_ssl) {
  113 + $server = RECAPTCHA_API_SECURE_SERVER;
  114 + } else {
  115 + $server = RECAPTCHA_API_SERVER;
  116 + }
  117 +
  118 + $errorpart = "";
  119 + if ($error) {
  120 + $errorpart = "&amp;error=" . $error;
  121 + }
  122 + return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
  123 +
  124 + <noscript>
  125 + <iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
  126 + <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
  127 + <input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
  128 + </noscript>';
  129 +}
  130 +
  131 +
  132 +
  133 +
  134 +/**
  135 + * A ReCaptchaResponse is returned from recaptcha_check_answer()
  136 + */
  137 +class ReCaptchaResponse {
  138 + var $is_valid;
  139 + var $error;
  140 +}
  141 +
  142 +
  143 +/**
  144 + * Calls an HTTP POST function to verify if the user's guess was correct
  145 + * @param string $privkey
  146 + * @param string $remoteip
  147 + * @param string $challenge
  148 + * @param string $response
  149 + * @param array $extra_params an array of extra variables to post to the server
  150 + * @return ReCaptchaResponse
  151 + */
  152 +function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
  153 +{
  154 + if ($privkey == null || $privkey == '') {
  155 + die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
  156 + }
  157 +
  158 + if ($remoteip == null || $remoteip == '') {
  159 + die ("For security reasons, you must pass the remote ip to reCAPTCHA");
  160 + }
  161 +
  162 +
  163 +
  164 + //discard spam submissions
  165 + if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
  166 + $recaptcha_response = new ReCaptchaResponse();
  167 + $recaptcha_response->is_valid = false;
  168 + $recaptcha_response->error = 'incorrect-captcha-sol';
  169 + return $recaptcha_response;
  170 + }
  171 +
  172 + $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
  173 + array (
  174 + 'privatekey' => $privkey,
  175 + 'remoteip' => $remoteip,
  176 + 'challenge' => $challenge,
  177 + 'response' => $response
  178 + ) + $extra_params
  179 + );
  180 +
  181 + $answers = explode ("\n", $response [1]);
  182 + $recaptcha_response = new ReCaptchaResponse();
  183 +
  184 + if (trim ($answers [0]) == 'true') {
  185 + $recaptcha_response->is_valid = true;
  186 + }
  187 + else {
  188 + $recaptcha_response->is_valid = false;
  189 + $recaptcha_response->error = $answers [1];
  190 + }
  191 + return $recaptcha_response;
  192 +
  193 +}
  194 +
  195 +/**
  196 + * gets a URL where the user can sign up for reCAPTCHA. If your application
  197 + * has a configuration page where you enter a key, you should provide a link
  198 + * using this function.
  199 + * @param string $domain The domain where the page is hosted
  200 + * @param string $appname The name of your application
  201 + */
  202 +function recaptcha_get_signup_url ($domain = null, $appname = null) {
  203 + return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
  204 +}
  205 +
  206 +function _recaptcha_aes_pad($val) {
  207 + $block_size = 16;
  208 + $numpad = $block_size - (strlen ($val) % $block_size);
  209 + return str_pad($val, strlen ($val) + $numpad, chr($numpad));
  210 +}
  211 +
  212 +/* Mailhide related code */
  213 +
  214 +function _recaptcha_aes_encrypt($val,$ky) {
  215 + if (! function_exists ("mcrypt_encrypt")) {
  216 + die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
  217 + }
  218 + $mode=MCRYPT_MODE_CBC;
  219 + $enc=MCRYPT_RIJNDAEL_128;
  220 + $val=_recaptcha_aes_pad($val);
  221 + return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
  222 +}
  223 +
  224 +
  225 +function _recaptcha_mailhide_urlbase64 ($x) {
  226 + return strtr(base64_encode ($x), '+/', '-_');
  227 +}
  228 +
  229 +/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
  230 +function recaptcha_mailhide_url($pubkey, $privkey, $email) {
  231 + if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
  232 + die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
  233 + "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
  234 + }
  235 +
  236 +
  237 + $ky = pack('H*', $privkey);
  238 + $cryptmail = _recaptcha_aes_encrypt ($email, $ky);
  239 +
  240 + return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
  241 +}
  242 +
  243 +/**
  244 + * gets the parts of the email to expose to the user.
  245 + * eg, given johndoe@example,com return ["john", "example.com"].
  246 + * the email is then displayed as john...@example.com
  247 + */
  248 +function _recaptcha_mailhide_email_parts ($email) {
  249 + $arr = preg_split("/@/", $email );
  250 +
  251 + if (strlen ($arr[0]) <= 4) {
  252 + $arr[0] = substr ($arr[0], 0, 1);
  253 + } else if (strlen ($arr[0]) <= 6) {
  254 + $arr[0] = substr ($arr[0], 0, 3);
  255 + } else {
  256 + $arr[0] = substr ($arr[0], 0, 4);
  257 + }
  258 + return $arr;
  259 +}
  260 +
  261 +/**
  262 + * Gets html to display an email address given a public an private key.
  263 + * to get a key, go to:
  264 + *
  265 + * http://www.google.com/recaptcha/mailhide/apikey
  266 + */
  267 +function recaptcha_mailhide_html($pubkey, $privkey, $email) {
  268 + $emailparts = _recaptcha_mailhide_email_parts ($email);
  269 + $url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
  270 +
  271 + return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
  272 + "' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
  273 +
  274 +}
  275 +
  276 +
  277 +?>
... ...
lib/smbind.class.php 0 → 100644
  1 +<?php
  2 +
  3 + require_once 'MDB2.php';
  4 + require_once 'punycode.class.php';
  5 +
  6 + $db = array();
  7 +
  8 + define('COMMENT_PATTERN', '/(\s+;|^;)[^\n]*/i');
  9 + define('ORIGIN_PATTERN', '/^\$ORIGIN\s+(.+)\.\s*/msi');
  10 + define('SOA_BEGINS_PATTERN', '/^([^\s]+)?(\s+[\d\w]+)?\s+IN\s+SOA\s+/msi');
  11 + define('FULL_SOA_PATTERN', '/^([^\s]+)?(\s+[\d\w]+)?\s+IN\s+SOA\s+([-\w\d.]*)\.\s+([-\w\d.]*)\s+\((.*)\)/msi');
  12 + define('TIMES_PATTERN', '/\s*(\d+\w?)\s+(\d+\w?)\s+(\d+\w?)\s+(\d+\w?)\s+(\d+\w?)/msi');
  13 + define('TXT_PATTERN', '/^\"(.*)\"/msi');
  14 + define('MX_PATTERN', '/^(\d+)\s+([^\s]*)/msi');
  15 + define('TYPE_PATTERN', '(A|A6|AAAA|AFSDB|APL|ATMA|AXFR|CERT|CNAME|DNAME|DNSKEY|DS|EID|GPOS|HINFO|ISDN|IXFR|KEY|KX|LOC|MAILB|MINFO|MX|NAPTR|NIMLOC|NS|NSAP|NSAP-PTR|NSEC|NXT|OPT|PTR|PX|RP|RRSIG|RT|SIG|SINK|SRV|SSHFP|TKEY|TSIG|TXT|WKS|X25)');
  16 + define('RECORD_PATTERN', '/^([^\s]+)?(\s+[\d][\d\w]*)?(\s+IN)?\s+'.TYPE_PATTERN.'\s+([^\s].*$)/msi');
  17 + define('BIND_TIME_PATTERN', '/^(\d+)([smhdw])/');
  18 + define('IDN_PUNY_PATTERN', '/[^a-z0-9-]/i');
  19 + define('IDN_UTF_PATTERN', '/[^a-z0-9\x80-\xFF-]/i');
  20 + define('BIND_ZONENAME_PATTERN', '/zone\s+"([^"]+)".*$/msi');
  21 + define('BIND_ZONEDATA_PATTERN', '/^([^\s]+)\s+"?([^"]+)"?$/');
  22 + define('BIND_SLAVEMASTER_PATTERN', '/^\{([^\};]+);}$/');
  23 +
  24 + function idnToHost($idn) {
  25 + preg_match(IDN_UTF_PATTERN, $idn, $match);
  26 + if (count($match) == 0) {
  27 + $out = ($idn > '') ? Punycode::encodeHostName($idn) : '';
  28 + return ((strlen($out) > 4) && (substr($out, 0, 4) == 'xn--')) ? $out : $idn;
  29 + }
  30 + $tags = explode($match[0], $idn);
  31 + $ret = array();
  32 + foreach ($tags as $tag) {
  33 + $ret[] = ($tag == '') ? '' : idnToHost($tag);
  34 + }
  35 + return implode($match[0], $ret);
  36 + }
  37 +
  38 + function hostToIdn($host) {
  39 + preg_match(IDN_PUNY_PATTERN, $host, $match);
  40 + if (count($match) == 0) {
  41 + return ((strlen($host) > 4) && (substr($host, 0, 4) == 'xn--')) ? Punycode::decodeHostName($host) : $host;
  42 + }
  43 + $tags = explode($match[0], $host);
  44 + $ret = array();
  45 + foreach ($tags as $tag) {
  46 + $ret[] = ($tag == '') ? '' : hostToIdn($tag, $match[0]);
  47 + }
  48 + return implode($match[0], $ret);
  49 + }
  50 +
  51 + class bindConfig {
  52 +
  53 + private $zonedef = array();
  54 + private $err = '';
  55 +
  56 + public function __debugInfo() {
  57 + return array(
  58 + 'zonedef' => $this->zonedef,
  59 + 'err' => $this->err,
  60 + );
  61 + }
  62 +
  63 + public function __construct($file = NULL) {
  64 + if (!is_null($file)) {
  65 + return $this->loadConfig($file);
  66 + } else {
  67 + $this->zonedef = array();
  68 + return true;
  69 + }
  70 + }
  71 +
  72 + public function getErr() {
  73 + return $this->err;
  74 + }
  75 +
  76 + public function loadConfig($fpath) {
  77 + if (!is_string($fpath)) {
  78 + $this->err .= "Only string parameter accepted\n";
  79 + error_log($this->err);
  80 + return false;
  81 + }
  82 + if ($fpath == '') {
  83 + $this->err .= "Given string is empty\n";
  84 + error_log($this->err);
  85 + return false;
  86 + }
  87 + if (!file_exists($fpath)) {
  88 + $this->err .= "File doesn't exist: '" . $fpath . "'\n";
  89 + error_log($this->err);
  90 + return false;
  91 + }
  92 + $conf = file($fpath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
  93 + $one = array();
  94 + $name = '';
  95 + foreach ($conf as $line) {
  96 + $line = preg_replace('/(\/\/.*|;)$/', '', trim($line));
  97 + if ($line == '') {
  98 + continue;
  99 + }
  100 + if ($name == '') {
  101 + preg_match(BIND_ZONENAME_PATTERN, $line, $match);
  102 + if (!isset($match[1])) {
  103 + $this->err .= "Read config error\n";
  104 + error_log($this->err);
  105 + return false;
  106 + }
  107 + $name = $match[1];
  108 + } else {
  109 + if ($line == '}') {
  110 + $this->zonedef[$name] = $one;
  111 + $one = array();
  112 + $name = '';
  113 + } else {
  114 + preg_match(BIND_ZONEDATA_PATTERN, $line, $match);
  115 + if ((!isset($match[1])) ||
  116 + (!isset($match[2]))) {
  117 + $this->err .= "Read config error\n";
  118 + error_log($this->err);
  119 + return false;
  120 + }
  121 + $key = $match[1];
  122 + $data = $match[2];
  123 + if ($key == 'masters') {
  124 + preg_match(BIND_SLAVEMASTER_PATTERN, $data, $match);
  125 + if (!isset($match[1])) {
  126 + $this->err .= "Read config error\n";
  127 + error_log($this->err);
  128 + return false;
  129 + }
  130 + $data = $match[1];
  131 + }
  132 + $one[$key] = $data;
  133 + }
  134 + }
  135 + }
  136 + return true;
  137 + }
  138 +
  139 + public function addConfig($name, $data) {
  140 + $name = strval($name);
  141 + if (($name == '') ||
  142 + (!is_array($data))) {
  143 + $this->err .= "Cannot set configset\n";
  144 + error_log($this->err);
  145 + return false;
  146 + }
  147 + $this->zonedef[$name] = $data;
  148 + return true;
  149 + }
  150 +
  151 + public function eraseConfig($name) {
  152 + $name = strval($name);
  153 + if ($name == '') {
  154 + $this->err .= "Cannot set configset\n";
  155 + error_log($this->err);
  156 + return false;
  157 + }
  158 + $this->zonedef[$name] = array();
  159 + return true;
  160 + }
  161 +
  162 + public function saveConfig($fname) {
  163 + if (!is_string($fname)) {
  164 + $this->err .= "Only string parameter accepted\n";
  165 + error_log($this->err);
  166 + return false;
  167 + }
  168 + if ($fname == '') {
  169 + $this->err .= "Given string is empty\n";
  170 + error_log($this->err);
  171 + return false;
  172 + }
  173 + $fh = fopen($fname,'w');
  174 + fwrite($fh, "// SMbind-ng configuration\n\n");
  175 + foreach($this->zonedef as $zone => $def) {
  176 + if (count($def) == 0) {
  177 + continue;
  178 + }
  179 + fwrite($fh, "// Zone " . hostToIdn($zone) . " (" . $def['type'] . ")\n");
  180 + fwrite($fh, "zone \"" . $zone . "\" {\n");
  181 + foreach ($def as $key => $param) {
  182 + switch ($key) {
  183 + case 'file':
  184 + $data = "\"" . $param . "\"";
  185 + break;
  186 + case 'masters':
  187 + $data = "{" . $param . ";}";
  188 + break;
  189 + default:
  190 + $data = $param;
  191 + }
  192 + fwrite($fh, str_pad($key, 10, " ", STR_PAD_LEFT) . " " . $data . ";\n");
  193 + }
  194 + fwrite($fh,"};\n\n");
  195 + }
  196 + fclose($fh);
  197 + return true;
  198 + }
  199 + }
  200 +
  201 + class Configuration {
  202 +
  203 + private $info = array();
  204 +
  205 + public function __debugInfo() {
  206 + return $this->info;
  207 + }
  208 +
  209 + public function __construct($conffile) {
  210 + global $db;
  211 + if (is_string($conffile)) {
  212 + include $conffile;
  213 + $dsn = $_CONF['db_type'] . "://" .
  214 + $_CONF['db_user'] . ":" .
  215 + $_CONF['db_pass'] . "@" .
  216 + $_CONF['db_host'] . "/" .
  217 + $_CONF['db_db'] .
  218 + '?charset=UTF8';
  219 + $db = MDB2::connect($dsn);
  220 + if (MDB2::isError($db)) {
  221 + die("Database error: " . MDB2::errorMessage($dbconnect));
  222 + } else {
  223 + $db->setFetchMode(MDB2_FETCHMODE_ASSOC);
  224 + }
  225 + $query = $db->query("SELECT prefkey, prefval FROM options WHERE preftype = 'normal'");
  226 + if (MDB2::isError($query)) {
  227 + $err = $query->getMessage() . "\n" . $query->getDebugInfo();
  228 + error_log($err);
  229 + die($err);
  230 + }
  231 + while ($res = $query->fetchRow()) {
  232 + $key = $res['prefkey'];
  233 + switch ($key) {
  234 + case 'prins':
  235 + case 'secns':
  236 + $keyparam = substr($key, 0, 3) . '_d' . substr($key, -2);
  237 + break;
  238 + default:
  239 + $keyparam = $key;
  240 + }
  241 + $_CONF[$keyparam] = $res['prefval'];
  242 + }
  243 + $query = $db->query("SELECT prefkey FROM options WHERE prefval = 'on' AND preftype = 'record' ORDER BY prefkey");
  244 + $_CONF['parameters'] = array();
  245 + while ($res = $query->fetchRow()) {
  246 + $_CONF['parameters'][] = $res['prefkey'];
  247 + }
  248 + $query = $db->query("SELECT DISTINCT type FROM records");
  249 + while ($res = $query->fetchRow()) {
  250 + $_CONF['parameters'][] = $res['type'];
  251 + }
  252 + $_CONF['parameters'] = array_unique($_CONF['parameters']);
  253 + $_CONF['dsn'] = $dsn;
  254 + $this->info = $_CONF;
  255 + }
  256 + }
  257 +
  258 + public function __call($method, $args) {
  259 + if (is_string($method)) {
  260 + $m = $this->from_CC(substr($method, 3, strlen($method) - 3));
  261 + return array_key_exists($m, $this->info) ? $this->info[$m] : false;
  262 + }
  263 + }
  264 +
  265 + public function __set($param, $arg) {
  266 + return true;
  267 + }
  268 +
  269 + public function __get($param) {
  270 + $name = strtolower($param);
  271 + $return = (array_key_exists($name, $this->info)) ? $this->info[$name] : NULL;
  272 + if (is_null($return)) {
  273 + switch ($name) {
  274 + case 'recaptcha':
  275 + $return = 'no';
  276 + break;
  277 + case 'nocaptcha':
  278 + $return = array();
  279 + break;
  280 + case 'namedcheckzone':
  281 + $return = '/usr/sbin/named-checkzone';
  282 + break;
  283 + case 'namedcheckconf':
  284 + $return = '/usr/sbin/named-checkconf';
  285 + break;
  286 + case 'rndc':
  287 + $return = '/usr/sbin/rndc';
  288 + break;
  289 + case 'range':
  290 + $return = 10;
  291 + break;
  292 + case 'title':
  293 + $return = 'SMbind-ng';
  294 + break;
  295 + case 'template':
  296 + $return = 'default';
  297 + break;
  298 + default:
  299 + $return = '';
  300 + }
  301 + }
  302 + return $return;
  303 + }
  304 +
  305 + private function from_CC($str) {
  306 + $str = strtolower($str);
  307 + $func = create_function('$c', 'return "_" . strtolower($c[1]);');
  308 + return preg_replace_callback('/([A-Z])/', $func, $str);
  309 + }
  310 +
  311 + public function isExists($id) {
  312 + return isset($this->info[strtolower($id)]);
  313 + }
  314 +
  315 + }
  316 +
  317 + class Session {
  318 +
  319 + private $usr = '';
  320 + private $psw = '';
  321 + private $inc = NULL;
  322 +
  323 + public function __debugInfo() {
  324 + return array(
  325 + 'usr' => $this->usr,
  326 + 'psw' => $this->psw,
  327 + 'inc' => $this->inc,
  328 + );
  329 + }
  330 +
  331 + public function __construct() {
  332 + session_start();
  333 + if ((isset($_SESSION['i'])) && (is_numeric($_SESSION['i'])) && ($_SESSION['i'] > 0)) {
  334 + $this->inc = $_SESSION['i'];
  335 + $this->inc++;
  336 + if ((isset($_SESSION['p'])) && (is_string($_SESSION['p']))) {
  337 + $this->psw = $_SESSION['p'];
  338 + if ((isset($_SESSION['u'])) && (is_string($_SESSION['u']))) {
  339 + $this->usr = $_SESSION['u'];
  340 + } else {
  341 + $this->psw = '';
  342 + }
  343 + }
  344 + } else {
  345 + $this->inc = 1;
  346 + }
  347 + $_SESSION['i'] = $this->inc;
  348 + }
  349 +
  350 + public function login($user, $pass) {
  351 + $_SESSION['u'] = $user;
  352 + $_SESSION['p'] = $pass;
  353 + $usr = $user;
  354 + $psw = $pass;
  355 + }
  356 +
  357 + public function destroy() {
  358 + $this->usr = '';
  359 + $this->psw = '';
  360 + $this->inc = 0;
  361 + $_SESSION = array();
  362 + session_destroy();
  363 + }
  364 +
  365 + public function isEnoughOld() {
  366 + return $this->inc > 3;
  367 + }
  368 + }
  369 +
  370 + class User {
  371 + private $data = array(
  372 + 'id' => 0,
  373 + 'username' => '',
  374 + 'realname' => '',
  375 + 'password' => '',
  376 + 'admin' => false,
  377 + );
  378 + private $mzones = array();
  379 + private $szones = array();
  380 + private $err = '';
  381 + private $db = array();
  382 +
  383 + public function __debugInfo() {
  384 + return array(
  385 + 'data' => $this->data,
  386 + 'mzones' => $this->mzones,
  387 + 'szones' => $this->szones,
  388 + 'err' => $this->err,
  389 + 'db' => NULL,
  390 + );
  391 + }
  392 +
  393 + public function __construct($uid = NULL) {
  394 + global $db;
  395 + $this->db = &$db;
  396 + if ((is_null($uid)) &&
  397 + (isset($_SESSION['i'])) &&
  398 + ($_SESSION['i'] > 1) &&
  399 + (isset($_SESSION['u'])) &&
  400 + ($_SESSION['p'])) {
  401 + $user = $_SESSION['u'];
  402 + $pass = $_SESSION['p'];
  403 + if (is_object($db)) {
  404 + if ((is_string($user)) && (is_string($pass))) {
  405 + $res = $this->db->query("SELECT * FROM users WHERE username ='" . $user . "' AND password = '" . $pass . "'");
  406 + if (MDB2::isError($res)) {
  407 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  408 + error_log($this->err);
  409 + return false;
  410 + } elseif ($res->numRows() == 0) {
  411 + $this->err .= "Username or password does not match";
  412 + error_log($this->err);
  413 + return false;
  414 + } else {
  415 + $row = $res->fetchRow();
  416 + foreach ($row as $key => $value) {
  417 + switch ($key) {
  418 + case 'id':
  419 + $this->data[$key] = intval($value);
  420 + break;
  421 + case 'admin':
  422 + $this->data[$key] = ($value == 'yes');
  423 + break;
  424 + default:
  425 + $this->data[$key] = strval($value);
  426 + }
  427 + }
  428 + $this->loadUserZones();
  429 + return true;
  430 + }
  431 + }
  432 + }
  433 + } elseif (((is_array($uid)) &&
  434 + (is_numeric($uid['id']))) ||
  435 + (is_numeric($uid))) {
  436 + $aid = (is_array($uid)) ? $uid : array('id' => $uid);
  437 + if ($aid['id'] == 0) {
  438 + foreach ($aid as $key => $value) {
  439 + $this->data[$key] = $value;
  440 + }
  441 + $this->data['username'] = ((isset($aid['username'])) && ($aid['username'] > '')) ? $aid['username'] : 'NONE';
  442 + $this->data['realname'] = ((isset($aid['realname'])) && ($aid['realname'] > '')) ? $aid['realname'] : $this->data['username'];
  443 + $this->data['password'] = ((isset($aid['password'])) && ($aid['password'] > '')) ? $aid['password'] : 'NONE';
  444 + $this->data['admin'] = ((isset($aid['admin'])) && ($aid['admin'] > '') && (($aid['admin'] == 'yes') || ($aid['admin'] == 'no'))) ? $aid['admin'] : 'no';
  445 + $res = $this->db->query("SELECT * FROM users WHERE username='" . $this->data['username'] . "'");
  446 + if (MDB2::isError($res)) {
  447 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  448 + error_log($this->err);
  449 + return false;
  450 + }
  451 + if ($res->numRows() > 0) {
  452 + $this->err .= ($this->data['username'] == 'NONE') ? "Previous error cause a problem\n" : "User already exists\n";
  453 + error_log($this->err);
  454 + return false;
  455 + }
  456 + $res = $this->db->query("INSERT INTO users (username, realname, admin, password) VALUES ('" .
  457 + $this->data['username'] . "', '" .
  458 + $this->data['realname'] . "', '" .
  459 + $this->data['admin'] . "', '" .
  460 + $this->data['password'] . "')");
  461 + if (MDB2::isError($res)) {
  462 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  463 + error_log($this->err);
  464 + return false;
  465 + }
  466 + $res = $this->db->query("SELECT id FROM users WHERE username='" .
  467 + $this->data['username'] . "' AND realname='" .
  468 + $this->data['realname'] . "' AND password='" .
  469 + $this->data['password'] . "'");
  470 + if (MDB2::isError($res)) {
  471 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  472 + error_log($this->err);
  473 + return false;
  474 + }
  475 + $ret = $res->fetchRow();
  476 + $this->data['id'] = $ret['id'];
  477 + return true;
  478 + } else {
  479 + $self->data['id'] = $aid['id'];
  480 + $res = $this->db->query("SELECT * FROM users WHERE id = '" . $self->data['id'] . "'");
  481 + if (MDB2::isError($res)) {
  482 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  483 + error_log($this->err);
  484 + return false;
  485 + } elseif ($res->numRows() == 0) {
  486 + $this->err .= "User not found with this id = " . $self->data['id'];
  487 + error_log($this->err);
  488 + return false;
  489 + } else {
  490 + $row = $res->fetchRow();
  491 + foreach ($row as $key => $value) {
  492 + switch ($key) {
  493 + case 'id':
  494 + $this->data[$key] = intval($value);
  495 + break;
  496 + case 'admin':
  497 + $this->data[$key] = ($value == 'yes');
  498 + break;
  499 + default:
  500 + $this->data[$key] = strval($value);
  501 + }
  502 + }
  503 + }
  504 + }
  505 + }
  506 + }
  507 +
  508 + public function loadUserZones() {
  509 + $WHERE = '';
  510 + if (!$this->isAdmin()) {
  511 + $WHERE .= "WHERE owner = '" . $this->getId() . "' ";
  512 + }
  513 + $res = $this->db->query("SELECT id FROM zones " . $WHERE . "ORDER BY name");
  514 + if (MDB2::isError($res)) {
  515 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  516 + error_log($this->err);
  517 + return false;
  518 + } else {
  519 + $this->mzones = array();
  520 + while ($rec = $res->fetchRow()) {
  521 + $this->mzones[] = $rec['id'];
  522 + }
  523 + $res = $this->db->query("SELECT id FROM slave_zones " . $WHERE . "ORDER BY name");
  524 + if (MDB2::isError($res)) {
  525 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  526 + error_log($this->err);
  527 + return false;
  528 + } else {
  529 + $this->szones = array();
  530 + while ($rec = $res->fetchRow()) {
  531 + $this->szones[] = $rec['id'];
  532 + }
  533 + }
  534 + }
  535 + return true;
  536 + }
  537 +
  538 + public function getUnvalidatedZones($zonetype = NULL) {
  539 + $ret = array();
  540 + if (is_string($zonetype)) {
  541 + $tag = '';
  542 + $db = NULL;
  543 + switch ($zonetype) {
  544 + case 'slave':
  545 + $tag = 'slave_';
  546 + $cnt = sizeof($this->szones);
  547 + $lst = implode(',', $this->szones);
  548 + break;
  549 + case 'master':
  550 + $cnt = sizeof($this->mzones);
  551 + $lst = implode(',', $this->mzones);
  552 + break;
  553 + }
  554 + if ($cnt > 0) {
  555 + $res = $this->db->query("SELECT id, name FROM " . $tag . "zones WHERE id IN (" . $lst . ") AND valid <> 'yes' and updated <> 'del'");
  556 + if (MDB2::isError($res)) {
  557 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  558 + error_log($this->err);
  559 + return false;
  560 + } else {
  561 + while ($recd = $res->fetchRow()) {
  562 + $recd['name'] = hostToIdn($recd['name']);
  563 + $ret[] = $recd;
  564 + }
  565 + }
  566 + }
  567 + }
  568 + return $ret;
  569 + }
  570 + public function getDeletedZones($zonetype = NULL) {
  571 + $ret = array();
  572 + if (is_string($zonetype)) {
  573 + $tag = '';
  574 + $db = NULL;
  575 + switch ($zonetype) {
  576 + case 'slave':
  577 + $tag = 'slave_';
  578 + $cnt = sizeof($this->szones);
  579 + $lst = implode(',', $this->szones);
  580 + break;
  581 + case 'master':
  582 + $cnt = sizeof($this->mzones);
  583 + $lst = implode(',', $this->mzones);
  584 + break;
  585 + }
  586 + if ($cnt > 0) {
  587 + $res = $this->db->query("SELECT id, name FROM " . $tag . "zones WHERE owner = " . $this->data['id'] . " AND updated = 'del'");
  588 + if (MDB2::isError($res)) {
  589 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  590 + error_log($this->err);
  591 + return false;
  592 + } else {
  593 + while ($recd = $res->fetchRow()) {
  594 + $recd['name'] = hostToIdn($recd['name']);
  595 + $ret[] = $recd;
  596 + }
  597 + }
  598 + }
  599 + }
  600 + return $ret;
  601 + }
  602 +
  603 + public function getCommitableZones($zonetype = NULL) {
  604 + $ret = array();
  605 + if (is_string($zonetype)) {
  606 + $tag = '';
  607 + $db = NULL;
  608 + switch ($zonetype) {
  609 + case 'slave':
  610 + $tag = 'slave_';
  611 + $cnt = sizeof($this->szones);
  612 + $lst = implode(',', $this->szones);
  613 + break;
  614 + case 'master':
  615 + $cnt = sizeof($this->mzones);
  616 + $lst = implode(',', $this->mzones);
  617 + break;
  618 + }
  619 + if ($cnt > 0) {
  620 + $res = $this->db->query("SELECT id, name FROM " . $tag . "zones WHERE id IN (" . $lst . ") AND valid = 'yes' AND updated = 'yes'");
  621 + if (MDB2::isError($res)) {
  622 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  623 + error_log($this->err);
  624 + return false;
  625 + } else {
  626 + while ($recd = $res->fetchRow()) {
  627 + $recd['name'] = hostToIdn($recd['name']);
  628 + $ret[] = $recd;
  629 + }
  630 + }
  631 + }
  632 + }
  633 + return $ret;
  634 + }
  635 +
  636 + public function eraseUser() {
  637 + $this->loadUserZones();
  638 + $mz =array();
  639 + foreach ($this->mzones as $master) {
  640 + $mz = new masterRecord($master);
  641 + $mz->loadZoneHead();
  642 + $mzh = $mz->getZoneHead();
  643 + $mzh['owner'] = 1;
  644 + $mz->setZoneHead($mzh);
  645 + $mz->saveZoneHead();
  646 + }
  647 + $mz =array();
  648 + $sz =array();
  649 + foreach ($this->szones as $slave) {
  650 + $sz = new slaveRecord($slave);
  651 + $sz->loadZoneHead();
  652 + $szh = $sz->getZoneHead();
  653 + $szh['owner'] = 1;
  654 + $sz->setZoneHead($szh);
  655 + $sz->saveZoneHead();
  656 + }
  657 + $sz =array();
  658 + $res = $this->db->query("DELETE FROM users WHERE id = " . $this->data['id']);
  659 + if (MDB2::isError($res)) {
  660 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  661 + error_log($this->err);
  662 + return false;
  663 + }
  664 + return true;
  665 + }
  666 +
  667 + public function getMasters($type = 'all') {
  668 + $out = array();
  669 + if ($type == 'live') {
  670 + foreach ($this->mzones as $zoneid) {
  671 + $zone = new masterZone(array('id' => intval($zoneid)));
  672 + $zone->loadZoneHead();
  673 + $head = $zone->getZoneHeadRaw();
  674 + if ($head['updated'] != 'del') {
  675 + $out[] = intval($zoneid);
  676 + }
  677 + }
  678 + } else {
  679 + $out = $this->mzones;
  680 + }
  681 + return $out;
  682 + }
  683 +
  684 + public function getSlaves($type = 'all') {
  685 + $out = array();
  686 + if ($type == 'live') {
  687 + foreach ($this->szones as $zoneid) {
  688 + $zone = new slaveZone(array('id' => intval($zoneid)));
  689 + $zone->loadZoneHead();
  690 + $head = $zone->getZoneHeadRaw();
  691 + if ($head['updated'] != 'del') {
  692 + $out[] = intval($zoneid);
  693 + }
  694 + }
  695 + } else {
  696 + $out = $this->szones;
  697 + }
  698 + return $out;
  699 + }
  700 +
  701 + public function isOwned($id, $type, $state = 'all') {
  702 + $zarr = array();
  703 + switch ($type) {
  704 + case 'master':
  705 + $zarr = $this->getMasters($state);
  706 + break;
  707 + case 'slave':
  708 + $zarr = $this->getSlaves($state);
  709 + break;
  710 + }
  711 + foreach ($zarr as $zid) {
  712 + if ($zid == $id) {
  713 + return true;
  714 + }
  715 + }
  716 + return false;
  717 + }
  718 +
  719 + public function getName() {
  720 + return $this->data['username'];
  721 + }
  722 +
  723 + public function getErr() {
  724 + return $this->err;
  725 + }
  726 +
  727 + public function getFullName() {
  728 + return $this->data['realname'];
  729 + }
  730 +
  731 + public function isAdmin() {
  732 + return $this->data['admin'];
  733 + }
  734 +
  735 + public function getId() {
  736 + return $this->data['id'];
  737 + }
  738 +
  739 + public function getPasswordHash() {
  740 + return $this->data['password'];
  741 + }
  742 +
  743 + public function getUser() {
  744 + $arr = array();
  745 + foreach (array('id', 'username', 'realname', 'admin') as $key) {
  746 + $arr[$key] = $this->data[$key];
  747 + }
  748 + return $arr;
  749 + }
  750 +
  751 + public function getAllusers() {
  752 + $out = array();
  753 + $res = $this->db->query("SELECT id, username, realname, admin FROM users ORDER BY realname");
  754 + if (MDB2::isError($res)) {
  755 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  756 + error_log($this->err);
  757 + } else {
  758 + while ($row = $res->fetchRow()) {
  759 + $out[] = $row;
  760 + }
  761 + }
  762 + return $out;
  763 + }
  764 +
  765 + public function loadUserById() {
  766 + $res = $this->db->query("SELECT * FROM users WHERE id = " . $this->data['id']);
  767 + if (MDB2::isError($res)) {
  768 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  769 + error_log($this->err);
  770 + return false;
  771 + } elseif ($res->numRows() == 0) {
  772 + $this->err .= "User not found";
  773 + error_log($this->err);
  774 + return false;
  775 + } else {
  776 + $row = $res->fetchRow();
  777 + foreach ($row as $key => $value) {
  778 + switch ($key) {
  779 + case 'id':
  780 + $this->data[$key] = intval($value);
  781 + break;
  782 + case 'admin':
  783 + $this->data[$key] = ($value == 'yes');
  784 + break;
  785 + default:
  786 + $this->data[$key] = strval($value);
  787 + }
  788 + }
  789 + return true;
  790 + }
  791 + }
  792 +
  793 + public function set($rname = NULL, $pass = NULL, $adm = NULL) {
  794 + if ((isset($pass)) || (isset($adm)) || (isset($rname))) {
  795 + $pstr = ((is_null($pass)) || (strlen($pass) != 32)) ? "" : "password = '" . $pass . "'";
  796 + $astr = ((is_null($adm)) || (($adm != 'yes') && ($adm != 'no'))) ? "" : "admin = '" . $adm . "'";
  797 + $rnstr = ((is_null($rname)) || ($rname == '')) ? "" : "realname = '" . $rname . "'";
  798 + $setstr = $pstr;
  799 + if ($astr > '') {
  800 + $setstr .= ($setstr != "") ? ", " . $astr : $astr;
  801 + }
  802 + if ($rnstr > '') {
  803 + $setstr .= ($setstr != "") ? ", " . $rnstr : $rnstr;
  804 + }
  805 + if ($setstr > "") {
  806 + $res = $this->db->query("UPDATE users SET " . $setstr . " WHERE id = " . $this->data['id']);
  807 + if (MDB2::isError($res)) {
  808 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  809 + error_log($this->err);
  810 + return false;
  811 + }
  812 + return $this->loadUserById();
  813 + } else {
  814 + return true;
  815 + }
  816 + } else {
  817 + return false;
  818 + }
  819 + }
  820 + }
  821 +
  822 + class masterRecord {
  823 +
  824 + private $record = array(
  825 + 'id' => NULL,
  826 + 'zone' => NULL,
  827 + 'host' => '',
  828 + 'type' => '',
  829 + 'pri' => 0,
  830 + 'destination' => '',
  831 + 'ttl' => 0,
  832 + );
  833 + private $db = NULL;
  834 + private $err = '';
  835 +
  836 + public function __debugInfo() {
  837 + return array(
  838 + 'record' => $this->record,
  839 + 'err' => $this->err,
  840 + 'db' => NULL,
  841 + );
  842 + }
  843 +
  844 + public function __construct($param = NULL) {
  845 + global $db;
  846 + if (is_object($db)) {
  847 + $this->db = &$db;
  848 + }
  849 + if (!is_null($param)) {
  850 + return $this->setRecord($param);
  851 + }
  852 + return true;
  853 + }
  854 +
  855 + public function getId() {
  856 + return $this->record['id'];
  857 + }
  858 +
  859 + private function fill_record($param) {
  860 + foreach ($param as $key => $value) {
  861 + switch ($key) {
  862 + case 'id':
  863 + case 'pri':
  864 + case 'ttl':
  865 + case 'zone':
  866 + $this->record[$key] = intval($value);
  867 + break;
  868 + case 'host':
  869 + $this->record[$key] = idnToHost($value);
  870 + break;
  871 + case 'type':
  872 + $this->record[$key] = strtoupper($value);
  873 + break;
  874 + case 'destination':
  875 + switch ($this->record['type']) {
  876 + case 'MX':
  877 + case 'CNAME':
  878 + case 'SRV':
  879 + case 'PTR':
  880 + case 'NS':
  881 + $this->record[$key] = idnToHost($value);
  882 + break;
  883 + default:
  884 + $this->record[$key] = strval($value);
  885 + }
  886 + break;
  887 + default:
  888 + $this->record[$key] = $value;
  889 + }
  890 + }
  891 + }
  892 +
  893 + public function setRecord($param) {
  894 + if (is_string($param)) {
  895 + if (!$this->parseRecord($param)) {
  896 + return false;
  897 + }
  898 + } elseif (is_numeric($param)) {
  899 + $this->record['id'] = $param;
  900 + } elseif (is_array($param)) {
  901 + $this->fill_record($param);
  902 + } else {
  903 + ob_start();
  904 + var_dump($param);
  905 + $this->err .= "Unidentified parameter" . "\n" . ob_get_clean();
  906 + error_log($this->err);
  907 + return false;
  908 + }
  909 + return true;
  910 + }
  911 +
  912 + private function bind_time_format($value) {
  913 + if (preg_match(BIND_TIME_PATTERN, strtolower($value), $match)) {
  914 + $value = $match[1];
  915 + switch ($match[2]) {
  916 + case "s":
  917 + $multiplier = 1;
  918 + break;
  919 + case "m":
  920 + $multiplier = 60;
  921 + break;
  922 + case "h":
  923 + $multiplier = 3600;
  924 + break;
  925 + case "d":
  926 + $multiplier = 86400;
  927 + break;
  928 + case "w":
  929 + $multiplier = 604800;
  930 + break;
  931 + }
  932 + $value = $value*$multiplier;
  933 + }
  934 + return $value;
  935 + }
  936 +
  937 + private function parseRecord($buffer) {
  938 + if (preg_match(RECORD_PATTERN, $buffer, $match)) {
  939 + $this->record['host'] = $match[1];
  940 + if ($this->record['host'] == '') {
  941 + $this->record['host'] = '@';
  942 + }
  943 + $this->record['type'] = strtoupper($match[4]);
  944 + if (isset($match[2])) {
  945 + $this->record['ttl'] = intval($this->bind_time_format($match[2]));
  946 + } else {
  947 + $this->record['ttl'] = 0;
  948 + }
  949 + switch ($this->record['type']) {
  950 + case 'MX':
  951 + if (preg_match(MX_PATTERN, $match[5], $match)) {
  952 + $this->record['pri'] = intval($match[1]);
  953 + $this->record['destination'] = idnToHost($match[2]);
  954 + } else {
  955 + ob_start();
  956 + var_dump($buffer);
  957 + $this->err .= "MX cannot be parsed" . "\n" . ob_get_clean();
  958 + error_log($this->err);
  959 + return NULL;
  960 + }
  961 + break;
  962 + case 'SRV':
  963 + case 'CNAME':
  964 + case 'NS':
  965 + case 'PTR':
  966 + $this->record['destination'] = idnToHost($match[5]);
  967 + break;
  968 + case 'TXT':
  969 + $this->record['destination'] = idnToHost(preg_replace('/(^"+|"+$|"+\s*"+)/msi', '', trim($match[5])));
  970 + break;
  971 + default:
  972 + $this->record['destination'] = $match[5];
  973 + }
  974 + return true;
  975 + } else {
  976 + ob_start();
  977 + var_dump($buffer);
  978 + $this->err .= "Record cannot be parsed" . "\n" . ob_get_clean();
  979 + error_log($this->err);
  980 + return false;
  981 + }
  982 + }
  983 +
  984 + public function getRecordRaw() {
  985 + return $this->record;
  986 + }
  987 +
  988 + public function getRecord() {
  989 + $out = $this->record;
  990 + $out['host'] = hostToIdn($out['host']);
  991 + switch ($out['type']) {
  992 + case 'MX':
  993 + case 'SRV':
  994 + case 'NS':
  995 + case 'CNAME':
  996 + case 'PTR':
  997 + $out['destination'] = hostToIdn($out['destination']);
  998 + }
  999 + return $out;
  1000 + }
  1001 +
  1002 + private function is_identified() {
  1003 + return (is_numeric($this->record['id']) && ($this->record['id'] > 0));
  1004 + }
  1005 +
  1006 + public function loadRecord() {
  1007 + if ($this->is_identified()) {
  1008 + $res = $this->db->query('SELECT * FROM records WHERE id =' . $this->record['id']);
  1009 + if (MDB2::isError($res)) {
  1010 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1011 + error_log($this->err);
  1012 + return false;
  1013 + } else {
  1014 + $row = $res->fetchRow();
  1015 + if (is_array($row)) {
  1016 + $this->fill_record($row);
  1017 + return true;
  1018 + } else {
  1019 + return NULL;
  1020 + }
  1021 + }
  1022 + } else {
  1023 + ob_start();
  1024 + var_dump($this-record);
  1025 + $this->err .= "Record is not identified" . "\n" . ob_get_clean();
  1026 + error_log($this->err);
  1027 + return false;
  1028 + }
  1029 + }
  1030 +
  1031 + public function getErr() {
  1032 + return $this->err;
  1033 + }
  1034 +
  1035 + private function is_complete() {
  1036 + return (($this->record['zone'] > 0) &&
  1037 + ($this->record['type'] > '') &&
  1038 + (
  1039 + ($this->record['host'] > '') ||
  1040 + ($this->record['destination'] > '')
  1041 + ));
  1042 + }
  1043 +
  1044 + private function find_record() {
  1045 + $res = $this->db->query("SELECT id FROM records WHERE " .
  1046 + "zone = " . $this->record['zone'] . " AND " .
  1047 + "host = '" . $this->record['host'] . "' AND " .
  1048 + "ttl = " . $this->record['ttl'] . " AND " .
  1049 + "type = '" . $this->record['type'] . "' AND " .
  1050 + "pri = " . $this->record['pri'] . " AND " .
  1051 + "destination = '" . $this->record['destination'] . "'"
  1052 + );
  1053 + if (MDB2::isError($res)) {
  1054 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1055 + error_log($this->err);
  1056 + return 0;
  1057 + } else {
  1058 + $value = $res->fetchRow();
  1059 + return $value['id'];
  1060 + }
  1061 + }
  1062 +
  1063 + public function saveRecord() {
  1064 + if ($this->is_complete()) {
  1065 + if ($this->record['host'] == '') {
  1066 + $this->record['host'] = '@';
  1067 + } elseif ($this->record['destination'] == '') {
  1068 + $this->record['destination'] = '@';
  1069 + }
  1070 + if ($this->record['type'] == 'MX') {
  1071 + $this->record['pri'] = ($this->record['pri'] == 0) ? 10 : $this->record['pri'];
  1072 + } else {
  1073 + $this->record['pri'] = 0;
  1074 + }
  1075 + if ((is_numeric($this->record['id'])) && ($this->record['id'] > 0)) {
  1076 + $res = $this->db->query("UPDATE records SET " .
  1077 + "zone = " . $this->record['zone'] . ", " .
  1078 + "host = '" . $this->record['host'] . "', " .
  1079 + "ttl = " . $this->record['ttl'] . ", " .
  1080 + "type = '" . $this->record['type'] . "', " .
  1081 + "pri = " . $this->record['pri'] . ", " .
  1082 + "destination = '" . $this->record['destination'] .
  1083 + "' WHERE id = " . $this->record['id']
  1084 + );
  1085 + if (MDB2::isError($res)) {
  1086 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1087 + error_log($this->err);
  1088 + return false;
  1089 + } else {
  1090 + return $this->loadRecord();
  1091 + }
  1092 + } else {
  1093 + $id = $this->find_record();
  1094 + if ($id > 0) {
  1095 + $this->record['id'] = $id;
  1096 + return true;
  1097 + } else {
  1098 + $res = $this->db->query("INSERT INTO records (zone, host, ttl, type, pri, destination) VALUES (" .
  1099 + $this->record['zone'] . ", '" .
  1100 + $this->record['host'] . "', " .
  1101 + $this->record['ttl'] . ", '" .
  1102 + $this->record['type'] . "', " .
  1103 + $this->record['pri'] . ", '" .
  1104 + $this->record['destination'] . "')"
  1105 + );
  1106 + if (MDB2::isError($res)) {
  1107 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1108 + error_log($this->err);
  1109 + return false;
  1110 + } else {
  1111 + $id = $this->find_record();
  1112 + if ($id > 0) {
  1113 + $this->record['id'] = $id;
  1114 + return true;
  1115 + } else {
  1116 + if ($this->err == '') {
  1117 + ob_start();
  1118 + var_dump($this->record);
  1119 + $this->err .= "Unknown write error" . "\n" . ob_get_clean();
  1120 + error_log($this->err);
  1121 + }
  1122 + return false;
  1123 + }
  1124 + }
  1125 + }
  1126 + }
  1127 + } else {
  1128 + ob_start();
  1129 + var_dump($this->record);
  1130 + $this->err .= "Record is not complete" . "\n" . ob_get_clean();
  1131 + error_log($this->err);
  1132 + return false;
  1133 + }
  1134 + }
  1135 +
  1136 + public function eraseRecord() {
  1137 + if ($this->is_identified()) {
  1138 + $res = $this->db->query("DELETE FROM records WHERE id = " . $this->record['id']);
  1139 + if (MDB2::isError($res)) {
  1140 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1141 + error_log($this->err);
  1142 + return false;
  1143 + } else {
  1144 + return true;
  1145 + }
  1146 + } else {
  1147 + ob_start();
  1148 + var_dump($this->record);
  1149 + $this->err .= "Record is not set" . "\n" . ob_get_clean();
  1150 + error_log($this->err);
  1151 + return false;
  1152 + }
  1153 + }
  1154 + }
  1155 +
  1156 + class slaveZone {
  1157 + private $head = array(
  1158 + 'id' => NULL,
  1159 + 'name' => '',
  1160 + 'master' => '',
  1161 + 'owner' => 0,
  1162 + 'updated' => 'no',
  1163 + 'valid' => 'may',
  1164 + );
  1165 + private $db = NULL;
  1166 + private $err = '';
  1167 +
  1168 + public function __debugInfo() {
  1169 + return array(
  1170 + 'head' => $this->head,
  1171 + 'err' => $this->err,
  1172 + 'db' => NULL,
  1173 + );
  1174 + }
  1175 +
  1176 + public function __construct($param = NULL) {
  1177 + global $db;
  1178 + if (is_object($db)) {
  1179 + $this->db = &$db;
  1180 + }
  1181 + if (!is_null($param)) {
  1182 + return $this->setZoneHead($param);
  1183 + }
  1184 + return true;
  1185 + }
  1186 +
  1187 + public function setZoneHead($param) {
  1188 + if (is_string($param)) {
  1189 + $this->head['name'] = idnToHost($param);
  1190 + } elseif (is_numeric($param)) {
  1191 + $this->head['id'] = $param;
  1192 + } elseif (is_array($param)) {
  1193 + $this->fill_head($param);
  1194 + } else {
  1195 + ob_start();
  1196 + var_dump($param);
  1197 + $this->err .= "Unidentified parameter" . "\n" . ob_get_clean();
  1198 + error_log($this->err);
  1199 + return false;
  1200 + }
  1201 + return true;
  1202 + }
  1203 +
  1204 + private function fill_head($param) {
  1205 + foreach ($param as $key => $value) {
  1206 + switch ($key) {
  1207 + case 'id':
  1208 + case 'owner':
  1209 + $this->head[$key] = intval($value);
  1210 + break;
  1211 + case 'master':
  1212 + case 'name':
  1213 + $this->head[$key] = idnToHost($value);
  1214 + break;
  1215 + default:
  1216 + $this->head[$key] = $value;
  1217 + }
  1218 + }
  1219 + }
  1220 +
  1221 + private function is_identified() {
  1222 + return ((isset($this->head['id'])) || ($this->head['name'] > ''));
  1223 + }
  1224 +
  1225 + private function notIdent($complete = false) {
  1226 + ob_start();
  1227 + var_dump($this->head);
  1228 + $head = ob_get_clean();
  1229 + if ($complete) {
  1230 + $this->err .= "Zone is not complete" . "\n" . $head;
  1231 + error_log($this->err);
  1232 + } else {
  1233 + $this->err .= "Unidentified zone" . "\n" . $head;
  1234 + error_log($this->err);
  1235 + }
  1236 + }
  1237 +
  1238 + public function loadZoneHead() {
  1239 + if ($this->is_identified()) {
  1240 + $where = ' WHERE ';
  1241 + if (isset($this->head['id'])) {
  1242 + $where .= "id = " . $this->head['id'];
  1243 + } else {
  1244 + $where .= "name = '" . $this->head['name'] . "'";
  1245 + }
  1246 + $res = $this->db->query("SELECT * FROM slave_zones" . $where);
  1247 + if (MDB2::isError($res)) {
  1248 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1249 + error_log($this->err);
  1250 + return false;
  1251 + } else {
  1252 + $row = $res->fetchRow();
  1253 + if (is_array($row)) {
  1254 + $this->fill_head($row);
  1255 + return true;
  1256 + } else {
  1257 + return NULL;
  1258 + }
  1259 + }
  1260 + } else {
  1261 + notIdent();
  1262 + return false;
  1263 + }
  1264 + }
  1265 +
  1266 + public function eraseZone() {
  1267 + if (!$this->is_identified()) {
  1268 + ob_start();
  1269 + var_dump($this->head);
  1270 + $this->err .= "Zone head is not complete" . "\n" . ob_get_clean();
  1271 + error_log($this->err);
  1272 + return false;
  1273 + } else {
  1274 + $where = ' WHERE ';
  1275 + if ($this->head['id'] >>= 0) {
  1276 + $where .= "id = " . $this->head['id'];
  1277 + } else {
  1278 + $where .= "name = '" . $this->head['name'] . "'";
  1279 + }
  1280 + $res = $this->db->query("DELETE FROM slave_zones " . $where);
  1281 + if (MDB2::isError($res)) {
  1282 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1283 + error_log($this->err);
  1284 + return false;
  1285 + }
  1286 + $this->clearZone();
  1287 + return true;
  1288 + }
  1289 + }
  1290 +
  1291 + public function clearZone() {
  1292 +
  1293 + $hd = array(
  1294 + 'id' => NULL,
  1295 + 'name' => '',
  1296 + 'master' => '',
  1297 + 'owner' => 0,
  1298 + 'updated' => 'no',
  1299 + 'valid' => 'may',
  1300 + );
  1301 + }
  1302 +
  1303 + public function dumpZone($dig) {
  1304 + if ($this->is_identified()) {
  1305 + if (!$this->is_complete()) {
  1306 + $this->loadZoneHead();
  1307 + }
  1308 + $cmd = $dig . " axfr @" . $this->head['master'] . " " . $this->head['name'] . ". +time=2 +tries=2 +retry=1 2>/dev/null";
  1309 + unset($coutput);
  1310 + exec($cmd, $coutput, $exit);
  1311 + $out = '';
  1312 + foreach ($coutput as $line) {
  1313 + $val = preg_replace('/(^;.*$|\r|\n)/', '', $line);
  1314 + $out .= ($val > '') ? $val . "\n" : '';
  1315 + }
  1316 + return $out;
  1317 + } else {
  1318 + $this->err .= "Zone identification failed\n";
  1319 + error_log($this->err);
  1320 + return false;
  1321 + }
  1322 + }
  1323 +
  1324 + public function validateZone($dig) {
  1325 + $out = $this->dumpZone($dig);
  1326 + if ((isset($out)) && ($out > '')) {
  1327 + return true;
  1328 + } elseif (isset($out)) {
  1329 + $err = "Zone transfer failed\n";
  1330 + error_log($err);
  1331 + $this->err .= $err;
  1332 + }
  1333 + return false;
  1334 + }
  1335 +
  1336 + public function getZoneHeadRaw() {
  1337 + return $this->head;
  1338 + }
  1339 +
  1340 + public function getZoneHead() {
  1341 + $out = array();
  1342 + foreach ($this->head as $key => $value) {
  1343 + switch ($key) {
  1344 + case 'master':
  1345 + case 'name':
  1346 + $out[$key] = hostToIdn($value);
  1347 + break;
  1348 + default:
  1349 + $out[$key] = $value;
  1350 + }
  1351 + }
  1352 + return $out;
  1353 + }
  1354 +
  1355 + public function getErr() {
  1356 + return $this->err;
  1357 + }
  1358 +
  1359 + private function is_complete() {
  1360 + return (($this->head['name'] > '') && ($this->head['master'] > '') && ($this->head['owner'] >0));
  1361 + }
  1362 +
  1363 + public function doCommit() {
  1364 + if (!$this->is_complete()) {
  1365 + ob_start();
  1366 + var_dump($this->head);
  1367 + $this->err .= "Zone head is not complete" . "\n" . ob_get_clean();
  1368 + error_log($this->err);
  1369 + return false;
  1370 + }
  1371 + $res = $this->db->query("UPDATE slave_zones SET " .
  1372 + "updated = 'no' " .
  1373 + "WHERE id = " . $this->head['id']);
  1374 + if (MDB2::isError($res)) {
  1375 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1376 + error_log($this->err);
  1377 + return false;
  1378 + }
  1379 + return $this->loadZoneHead();
  1380 + }
  1381 +
  1382 + public function saveZoneHead() {
  1383 + if (!$this->is_complete()) {
  1384 + ob_start();
  1385 + var_dump($this->head);
  1386 + $this->err .= "Zone head is not complete" . "\n" . ob_get_clean();
  1387 + error_log($this->err);
  1388 + return false;
  1389 + }
  1390 + if (!isset($this->head['id'])) {
  1391 + $vld = (isset($this->head['valid'])) ? $this->head['valid'] : 'may';
  1392 + $upd = 'yes';
  1393 + $res = $this->db->query("INSERT INTO slave_zones " .
  1394 + "(name, master, valid, owner, updated) " .
  1395 + "VALUES ('" . $this->head['name'] .
  1396 + "', '" . $this->head['master'] .
  1397 + "', '" . $vld .
  1398 + "', " . $this->head['owner'] .
  1399 + ", '" . $upd .
  1400 + "')");
  1401 + if (MDB2::isError($res)) {
  1402 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1403 + error_log($this->err);
  1404 + return false;
  1405 + }
  1406 + return $this->loadZoneHead();
  1407 + } else {
  1408 + $vld = (($this->head['valid'] == 'yes') || ($this->head['valid'] == 'no')) ? $this->head['valid'] : 'may';
  1409 + $upd = ((isset($this->head['updated'])) && ($this->head['updated'] != 'del')) ? 'yes' : $this->head['updated'];
  1410 + $res = $this->db->query("UPDATE slave_zones SET " .
  1411 + "name = '" . $this->head['name'] . "', " .
  1412 + "master = '" . $this->head['master'] . "', " .
  1413 + "valid = '" . $vld . "', " .
  1414 + "owner = " . $this->head['owner'] . ", " .
  1415 + "updated = '" . $upd . "' " .
  1416 + "WHERE id = " . $this->head['id']);
  1417 + if (MDB2::isError($res)) {
  1418 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1419 + error_log($this->err);
  1420 + return false;
  1421 + }
  1422 + return $this->loadZoneHead();
  1423 + }
  1424 + }
  1425 +
  1426 + }
  1427 +
  1428 + class masterZone {
  1429 +
  1430 + private $head = array(
  1431 + 'id' => NULL,
  1432 + 'name' => '',
  1433 + 'pri_dns' => '',
  1434 + 'sec_dns' => '',
  1435 + 'serial' => 0,
  1436 + 'refresh' => 0,
  1437 + 'retry' => 0,
  1438 + 'expire' => 0,
  1439 + 'ttl' => 0,
  1440 + 'valid' => 'may',
  1441 + 'owner' => 0,
  1442 + 'updated' => 'no',
  1443 + 'secured' => 'no',
  1444 + );
  1445 + private $db = NULL;
  1446 + private $records = array();
  1447 + private $err = '';
  1448 + private $isloaded = FALSE;
  1449 + private $msg = '';
  1450 +
  1451 + public function __debugInfo() {
  1452 + return array(
  1453 + 'head' => $this->head,
  1454 + 'records' => $this->records,
  1455 + 'err' => $this->err,
  1456 + 'isloaded' => $this->isloaded,
  1457 + 'msg' => $this->msg,
  1458 + 'db' => NULL,
  1459 + );
  1460 + }
  1461 +
  1462 + public function __construct($param = NULL) {
  1463 + global $db;
  1464 + if (is_object($db)) {
  1465 + $this->db = &$db;
  1466 + }
  1467 + if (!is_null($param)) {
  1468 + return $this->setZoneHead($param);
  1469 + }
  1470 + return true;
  1471 + }
  1472 +
  1473 + public function getZoneHeadRaw() {
  1474 + return $this->head;
  1475 + }
  1476 +
  1477 + private function tab_to_space($line, $tab = 8, $nbsp = FALSE) {
  1478 + while (($t = mb_strpos($line,"\t")) !== FALSE) {
  1479 + $preTab = $t ? mb_substr($line, 0, $t) : '';
  1480 + $line = $preTab . str_repeat($nbsp?chr(7):' ', $tab-(mb_strlen($preTab)%$tab)) . mb_substr($line, $t+1);
  1481 + }
  1482 + return $nbsp ? str_replace($nbsp?chr(7):' ', '&nbsp;', $line) : $line;
  1483 + }
  1484 +
  1485 + private function split_text_record($line, $length = 76) {
  1486 + $line = $this->tab_to_space($line);
  1487 + $slices = $line;
  1488 + if(strlen($line) > $length) {
  1489 + $pos = stripos($line, "\"");
  1490 + if ($pos !== false) {
  1491 + if($pos>$length-2) {
  1492 + $slices = substr($line, 0, $pos) . "(\n";
  1493 + $line = $this->tab_to_space("\t\t\t\t\t" . substr($line,$pos) . " )");
  1494 + } else {
  1495 + $allline = substr($line,0,$pos) . "( " . substr($line,$pos) . " )";
  1496 + $slices = substr($allline,0,$length-1) . "\"\n";
  1497 + $line = $this->tab_to_space("\t\t\t\t\t\t \"" . substr($allline,$length-1));
  1498 + }
  1499 + while (strlen($line) > $length) {
  1500 + $slices .= substr($line, 0, $length-1) . "\"\n";
  1501 + $line = $this->tab_to_space("\t\t\t\t\t\t \"" . substr($line,$length-1));
  1502 + }
  1503 + if(strlen($line) > 0) { $slices .= $line; }
  1504 + }
  1505 + }
  1506 + return $slices;
  1507 + }
  1508 +
  1509 + private function prettyer($name,$ttl,$type,$pri,$target) {
  1510 + $line = str_pad($name, 31) . " " . $ttl . "\t" . "IN " . "$type";
  1511 + if (strlen($type)<5) {
  1512 + $line .= "\t";
  1513 + }
  1514 + $line .= " " . $pri;
  1515 + if (strlen($pri) > 0){
  1516 + $line .= " ";
  1517 + }
  1518 + if ($type == "TXT"){
  1519 + $target = "\"" . $target . "\"";
  1520 + }
  1521 + return $this->split_text_record($line . $target, 116);
  1522 + }
  1523 +
  1524 +
  1525 + public function getConf($hostmaster) {
  1526 + $out = "\$TTL " . $this->head['ttl'] . "\n";
  1527 + $out .= $this->prettyer("@", "", "SOA", "", $this->head['pri_dns'] . ". " . $hostmaster . ".") . " (\n";
  1528 + $out .= $this->tab_to_space("\t\t\t\t\t" . $this->head['serial'] . "\t; Serial\n") .
  1529 + $this->tab_to_space("\t\t\t\t\t" . $this->head['refresh'] . "\t\t; Refresh\n") .
  1530 + $this->tab_to_space("\t\t\t\t\t" . $this->head['retry'] . "\t\t; Retry\n") .
  1531 + $this->tab_to_space("\t\t\t\t\t" . $this->head['expire'] . "\t\t; Expire\n") .
  1532 + $this->tab_to_space("\t\t\t\t\t" . $this->head['ttl'] . ")\t\t; Negative Cache TTL\n;\n");
  1533 + foreach (array('pri_dns', 'sec_dns') as $ns) {
  1534 + $out .= ($this->head[$ns] != '') ? $this->prettyer("@",'','NS','',$this->head[$ns] . ".") . "\n" : "";
  1535 + }
  1536 + foreach ($this->getRecordsRaw() as $record) {
  1537 + $row = $record->getRecordRaw();
  1538 + $pri = ($row['type'] == 'MX') ? $row['pri'] : '';
  1539 + $ttl = ($row['ttl'] > 0) ? $row['ttl'] : '';
  1540 + $out .= $this->prettyer($row['host'],$ttl,$row['type'],$pri,$row['destination']) . "\n";
  1541 + }
  1542 + return $out;
  1543 + }
  1544 +
  1545 + public function getMsg() {
  1546 + return $this->msg;
  1547 + }
  1548 +
  1549 + public function writeZone($file, $hostmaster) {
  1550 + if (!$this->isloaded) {
  1551 + if (!$this->loadZone()) {
  1552 + $this->err .= "Unable to load zone\n";
  1553 + error_log ($this->err);
  1554 + return false;
  1555 + }
  1556 + }
  1557 + $zonedata = $this->getConf($hostmaster);
  1558 + $fh = fopen($file, "w");
  1559 + fwrite($fh, $zonedata . "\n");
  1560 + fclose($fh);
  1561 + return true;
  1562 + }
  1563 +
  1564 + public function validateZone($file, $hostmaster, $checkzonecmd) {
  1565 + if ($this->writeZone($file, $hostmaster)) {
  1566 + $cmd = $checkzonecmd . " -i local " . $this->head['name'] . " " . $file . " 2>/dev/stdout";
  1567 + unset($coutput);
  1568 + exec($cmd, $coutput, $exit);
  1569 + $rows = sizeof($coutput);
  1570 + $return[0] = ($coutput[$rows-1] == 'OK');
  1571 + if (($return[0]) && ($exit == 0)) {
  1572 + $rows--;
  1573 + $return[1] = '';
  1574 + } else {
  1575 + $return[1] = 'Exitcode: ' . $exit . "\n";
  1576 + }
  1577 + $return[1] .= implode("<br />", $coutput);
  1578 + if (!$return[0]) {
  1579 + $this->err = $return[1];
  1580 + error_log("ERROR\nCMD: " . $cmd . "\nExit: " . $exit . "\n" . implode("\n", $coutput));
  1581 + $this->head['valid'] = 'no';
  1582 + } else {
  1583 + $this->head['valid'] = 'yes';
  1584 + }
  1585 + $this->saveZoneHead();
  1586 + return $return;
  1587 + }
  1588 + $log = "Zone cannot be validate\n";
  1589 + $this->err .= $log;
  1590 + error_log($log);
  1591 + return array(false,"Problem in prerequisites\n");
  1592 + }
  1593 +
  1594 + public function getZoneHead() {
  1595 + $out = array();
  1596 + foreach ($this->head as $key => $value) {
  1597 + switch ($key) {
  1598 + case 'pri_dns':
  1599 + case 'sec_dns':
  1600 + case 'name':
  1601 + $out[$key] = hostToIdn($value);
  1602 + break;
  1603 + default:
  1604 + $out[$key] = $value;
  1605 + }
  1606 + }
  1607 + return $out;
  1608 + }
  1609 +
  1610 + public function getErr() {
  1611 + return $this->err;
  1612 + }
  1613 +
  1614 + public function getId() {
  1615 + return $this->head['id'];
  1616 + }
  1617 +
  1618 + private function fill_head($param) {
  1619 + foreach ($param as $key => $value) {
  1620 + switch ($key) {
  1621 + case 'id':
  1622 + case 'serial':
  1623 + case 'retry':
  1624 + case 'refresh':
  1625 + case 'expire':
  1626 + case 'ttl':
  1627 + case 'owner':
  1628 + $this->head[$key] = intval($value);
  1629 + break;
  1630 + case 'pri_dns':
  1631 + case 'sec_dns':
  1632 + case 'name':
  1633 + $this->head[$key] = idnToHost($value);
  1634 + break;
  1635 + default:
  1636 + $this->head[$key] = $value;
  1637 + }
  1638 + }
  1639 + }
  1640 +
  1641 + public function setZoneHead($param) {
  1642 + if (is_string($param)) {
  1643 + $this->head['name'] = idnToHost($param);
  1644 + } elseif (is_numeric($param)) {
  1645 + $this->head['id'] = $param;
  1646 + } elseif (is_array($param)) {
  1647 + $this->fill_head($param);
  1648 + } else {
  1649 + ob_start();
  1650 + var_dump($param);
  1651 + $this->err .= "Unidentified parameter" . "\n" . ob_get_clean();
  1652 + error_log($this->err);
  1653 + return false;
  1654 + }
  1655 + return true;
  1656 + }
  1657 +
  1658 + private function is_identified() {
  1659 + return ((isset($this->head['id'])) || ($this->head['name'] > ''));
  1660 + }
  1661 +
  1662 + private function notIdent($complete = false) {
  1663 + ob_start();
  1664 + var_dump($this->head);
  1665 + $head = ob_get_clean();
  1666 + if ($complete) {
  1667 + $this->err .= "Zone is not complete" . "\n" . $head;
  1668 + error_log($this->err);
  1669 + } else {
  1670 + $this->err .= "Unidentified zone" . "\n" . $head;
  1671 + error_log($this->err);
  1672 + }
  1673 + }
  1674 +
  1675 + public function loadZoneHead() {
  1676 + if ($this->is_identified()) {
  1677 + $where = ' WHERE ';
  1678 + if (isset($this->head['id'])) {
  1679 + $where .= "id = " . $this->head['id'];
  1680 + } else {
  1681 + $where .= "name = '" . $this->head['name'] . "'";
  1682 + }
  1683 + $res = $this->db->query("SELECT * FROM zones" . $where);
  1684 + if (MDB2::isError($res)) {
  1685 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1686 + error_log($this->err);
  1687 + return false;
  1688 + } else {
  1689 + $row = $res->fetchRow();
  1690 + if (is_array($row)) {
  1691 + $this->fill_head($row);
  1692 + return true;
  1693 + } else {
  1694 + return NULL;
  1695 + }
  1696 + }
  1697 + } else {
  1698 + $this->notIdent();
  1699 + return false;
  1700 + }
  1701 + }
  1702 +
  1703 + public function loadZoneRecords() {
  1704 + if ($this->is_complete()) {
  1705 + $res = $this->db->query("SELECT id FROM records WHERE zone = " . $this->head['id']);
  1706 + if (MDB2::isError($res)) {
  1707 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  1708 + error_log($this->err);
  1709 + return false;
  1710 + } else {
  1711 + while ($row = $res->fetchRow()) {
  1712 + $id = intval($row['id']);
  1713 + $this->records[$id] = new masterRecord($row);
  1714 + if (!$this->records[$id]->loadRecord()) {
  1715 + $this->err .= $this->records[$id]->getErr();
  1716 + error_log($this->err);
  1717 + return false;
  1718 + }
  1719 + }
  1720 + return true;
  1721 + }
  1722 + } else {
  1723 + notIdent(true);
  1724 + return false;
  1725 + }
  1726 + }
  1727 +
  1728 + public function eraseRecord($id) {
  1729 + $found = false;
  1730 + foreach ($this->records as $key => $entry) {
  1731 + if ($key == $id) {
  1732 + $found = true;
  1733 + if (!$entry->eraseRecord()) {
  1734 + $this->err .= $entry->getErr();
  1735 + error_log($this->err);
  1736 + return false;
  1737 + }
  1738 + }
  1739 + }
  1740 + if ($found) {
  1741 + $this->head['valid'] = 'may';
  1742 + $this->saveZoneHead();
  1743 + $this->records = array();
  1744 + $this->loadZoneRecords();
  1745 + return true;
  1746 + }
  1747 + $this->err .= "Record id not found" . "\n" . $id;
  1748 + error_log($this->err);
  1749 + return false;
  1750 + }
  1751 +
  1752 + public function addRecord($param = NULL) {
  1753 + if ((is_numeric($this->head['id'])) && ($this->head['id'] > 0)) {
  1754 + $nrec = new masterRecord($param);
  1755 + $nrec->setRecord(array( 'zone' => $this->head['id']));
  1756 + $urec = $nrec->getRecord();
  1757 + if ((
  1758 + ($urec['host'] > '') ||
  1759 + ($urec['destination'] > '')
  1760 + ) &&
  1761 + ($urec['host'] != $urec['destination']) &&
  1762 + ($urec['type'] > '')) {
  1763 + $this->records[] = $nrec;
  1764 + $this->head['valid'] = 'may';
  1765 + return true;
  1766 + } else {
  1767 + ob_start();
  1768 + var_dump($param);
  1769 + $this->err .= "Record is empty" . "\n" . ob_get_clean();
  1770 + error_log($this->err);
  1771 + return false;
  1772 + }
  1773 + } else {
  1774 + ob_start();
  1775 + var_dump($this->head);
  1776 + $this->err .= "Zone has not defined yet" . "\n" . ob_get_clean();
  1777 + error_log($this->err);
  1778 + return false;
  1779 + }
  1780 + }
  1781 +
  1782 + private function bind_time_format($value) {
  1783 + if (preg_match(BIND_TIME_PATTERN, strtolower($value), $match)) {
  1784 + $value = $match[1];
  1785 + switch ($match[2]) {
  1786 + case "s":
  1787 + $multiplier = 1;
  1788 + break;
  1789 + case "m":
  1790 + $multiplier = 60;
  1791 + break;
  1792 + case "h":
  1793 + $multiplier = 3600;
  1794 + break;
  1795 + case "d":
  1796 + $multiplier = 86400;
  1797 + break;
  1798 + case "w":
  1799 + $multiplier = 604800;
  1800 + break;
  1801 + }
  1802 + $value = $value*$multiplier;
  1803 + }
  1804 + return $value;
  1805 + }
  1806 +
  1807 +
  1808 + public function parseZone($rows, $zonename, $owner = 1) {
  1809 + if (!is_array($rows)) {
  1810 + ob_start();
  1811 + var_dump($rows);
  1812 + $this->err .= "Zone can be parsed from an array only" . "\n" . ob_get_clean();
  1813 + error_log($this->err);
  1814 + return false;
  1815 + } else {
  1816 + $this->clearZone();
  1817 + $this->head['name'] = idnToHost($zonename);
  1818 + $soafound = false;
  1819 + $soabegins = false;
  1820 + $soadata = '';
  1821 + $recrow = '';
  1822 + foreach ($rows as $row) {
  1823 + $row = preg_replace(COMMENT_PATTERN, ' ', trim($row));
  1824 + $row = ($row == " ") ? '' : $row;
  1825 + if ($soafound === false) {
  1826 + if (preg_match(ORIGIN_PATTERN, $row, $match)) {
  1827 + $zone = strtolower($match[1]);
  1828 + if ($zone != $expectedname) {
  1829 + $this->clearZone();
  1830 + $this->err .= "Given zone not matches with the expected (" . $zone . "<=>" . $expectedzone . ")";
  1831 + error_log($this->err);
  1832 + return false;
  1833 + }
  1834 + }
  1835 + if (preg_match(SOA_BEGINS_PATTERN, $row, $match)) {
  1836 + $soabegins = true;
  1837 + }
  1838 + if ($soabegins) {
  1839 + $soadata .= $row;
  1840 + }
  1841 + if (preg_match(FULL_SOA_PATTERN, $soadata, $match)) {
  1842 + $prins = $match[3];
  1843 + if(preg_match(TIMES_PATTERN, $match[5], $match2)) {
  1844 + $soafound = true;
  1845 + $serial = $match2[1];
  1846 + $refresh = $this->bind_time_format($match2[2]);
  1847 + $retry = $this->bind_time_format($match2[3]);
  1848 + $expire = $this->bind_time_format($match2[4]);
  1849 + $ttl = $this->bind_time_format($match2[5]);
  1850 + if (($this->setZoneHead(
  1851 + array(
  1852 + 'serial' => intval($serial),
  1853 + 'refresh' => intval($refresh),
  1854 + 'retry' => intval($retry),
  1855 + 'expire' => intval($expire),
  1856 + 'ttl' => intval($ttl),
  1857 + 'owner' => intval($owner),
  1858 + 'pri_dns' => strval($prins),
  1859 + 'sec_dns' => '##EMPTY##',
  1860 + ))) && ($this->saveZoneHead())) {
  1861 + $soafound = true;
  1862 + } else {
  1863 + $this->err .= "Head cannot be set" . "\n" . $soadata;
  1864 + $this->clearZone();
  1865 + return false;
  1866 + }
  1867 + } else {
  1868 + $this->err .= "SOA record cannot be parsed" . "\n" . $soadata;
  1869 + error_log($this->err);
  1870 + return false;
  1871 + }
  1872 + }
  1873 + } else {
  1874 + if ($recrow != '') {
  1875 + $rowpart = trim($row);
  1876 + $recrow .= $rowpart;
  1877 + $end = strpos($recrow, ')');
  1878 + if ($end > 0) {
  1879 + $recrow = substr($recrow, 0, $end);
  1880 + $recd = new masterRecord(array('zone' => $this->head['id']));
  1881 + if ($recd->setRecord($recrow)) {
  1882 + $parsed = $recd->getRecordRaw();
  1883 + if (
  1884 + ($this->head['sec_dns'] == '##EMPTY##') &&
  1885 + ($parsed['type'] == 'NS') &&
  1886 + ($parsed['destination'] != $self->head['pri_dns']) &&
  1887 + (
  1888 + ($parsed['host'] == '@') ||
  1889 + ($parsed['host'] == '')
  1890 + )
  1891 + ) {
  1892 + $self->head['sec_dns'] == $parsed['destination'];
  1893 + }
  1894 + $this->records[] = $recd;
  1895 + $recrow = '';
  1896 + } else {
  1897 + $this->err .= $recd->getErr();
  1898 + return false;
  1899 + }
  1900 + }
  1901 + } elseif ($row > '') {
  1902 + $end = strpos($row, '(');
  1903 + if ($end > 0) {
  1904 + $row = preg_replace('/\(/', '', $row);
  1905 + $recrow = $row;
  1906 + }
  1907 + $end = strpos($recrow, ')');
  1908 + if ($end > 0) {
  1909 + $recrow = substr($recrow, 0, $end);
  1910 + $recd = new masterRecord(array('zone' => $this->head['id']));
  1911 + if ($recd->setRecord($recrow, $this->head['name'])) {
  1912 + $this->records[] = $recd;
  1913 + $recrow = '';
  1914 + } else {
  1915 + $this->err .= $recd->getErr();
  1916 + return false;
  1917 + }
  1918 + } elseif ($recrow == '') {
  1919 + $recd = new masterRecord(array('zone' => $this->head['id']));
  1920 + if ($recd->setRecord($row, $this->head['name'])) {
  1921 + $this->records[] = $recd;
  1922 + } else {
  1923 + $this->err .= $recd->getErr();
  1924 + return false;
  1925 + }
  1926 + }
  1927 + }
  1928 + }
  1929 + }
  1930 + $recs = array();
  1931 + foreach ($this->records as $each) {
  1932 + $rhd = $each->getRecordRaw();
  1933 + if (($rhd['type'] == 'NS')) {
  1934 + if (($rhd['host'] == '@') && ($rhd['destination'] == $this->head['pri_dns'] . '.')) {
  1935 + continue;
  1936 + } elseif ($rhd['host'] == '@') {
  1937 + $this->head['sec_dns'] = ($this->head['sec_dns'] == '##EMPTY##') ? preg_replace('/\.$/', '', $rhd['destination']) : $this->head['sec_dns'];
  1938 + continue;
  1939 + }
  1940 + }
  1941 + $recs[] = $each;
  1942 + }
  1943 + $this->records = $recs;
  1944 + $this->saveZone();
  1945 + }
  1946 + return true;
  1947 + }
  1948 +
  1949 + public function loadZone() {
  1950 + $ret = $this->loadZoneHead();
  1951 + if (($ret) && (!is_null($this->head['id']))) {
  1952 + $this->isloaded = $this->loadZoneRecords();
  1953 + return $this->isloaded;
  1954 + } elseif (is_null($ret)) {
  1955 + return NULL;
  1956 + } else {
  1957 + return false;
  1958 + }
  1959 + }
  1960 +
  1961 + public function getRecordsRaw() {
  1962 + return $this->records;
  1963 + }
  1964 +
  1965 + public function getRecords($ordered = false) {
  1966 + $out = array();
  1967 + foreach ($this->records as $key => $each) {
  1968 + if ($ordered) {
  1969 + $out[] = $each->getRecord();
  1970 + } else {
  1971 + $out[$key] = $each->getRecord();
  1972 + }
  1973 + }
  1974 + return $out;
  1975 + }
  1976 +
  1977 + public function getZoneRaw() {
  1978 + $out = array();
  1979 + $out[] = $this->getZoneHeadRaw();
  1980 + $out[] = $this->getRecordsRaw();
  1981 + }
  1982 +
  1983 + public function getZone() {
  1984 + $out = array();
  1985 + $out[] = $this->getZoneHead();
  1986 + $out[] = $this->getRecords();
  1987 + return $out;
  1988 + }
  1989 +
  1990 + public function refresh_secure($zonedir) {
  1991 +
  1992 + $files = glob($zonedir . "{K,dsset-,}" . $this->head['name'] . ".{*private,*key,krf,}", GLOB_BRACE);
  1993 + $hit = 0;
  1994 + $names = array();
  1995 + foreach ($files as $key => $file) {
  1996 + $name = basename($file);
  1997 + switch ($name) {
  1998 + case $this->head['name'] . '.krf':
  1999 + case 'dsset-' . $this->head['name'] . '.':
  2000 + $hit++;
  2001 + break;
  2002 + default:
  2003 + $pattern = '/^K' . $this->head['name'] . '\.\+\d+\+\d+\.(private|key)/';
  2004 + preg_match($pattern, $name, $match);
  2005 + $hit += ($match[0] == $name) ? 1 : 0;
  2006 + }
  2007 + $names[$key] = $name;
  2008 + }
  2009 + $filesok = ($hit >= 8);
  2010 + $res = $this->db->query("SELECT id, dsset, krf FROM dnssec_zones WHERE zone = " . $this->head['id']);
  2011 + if (MDB2::isError($res)) {
  2012 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2013 + error_log($this->err);
  2014 + return false;
  2015 + }
  2016 + $dbok = ($res->numRows() == 1);
  2017 + if ($dbok) {
  2018 + $sel = $res->fetchRow();
  2019 + $id = $sel['id'];
  2020 + $dsset = $sel['dsset'];
  2021 + $krf = $sel['krf'];
  2022 + if ($filesok) {
  2023 + $dssetf = file_get_contents($zonedir . "dsset-" . $this->head['name'] . '.');
  2024 + $krff = file_get_contents($zonedir . $this->head['name'] . '.krf');
  2025 + if (($dsset != $dssetf) || ($krf != $krff)) {
  2026 + $res = $this->db->query("UPDATE dnssec_zones SET " .
  2027 + "dsset = '" . $dssetf . "', " .
  2028 + "krf = '" . $krff . "' WHERE id = " . $id
  2029 + );
  2030 + if (MDB2::isError($res)) {
  2031 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2032 + error_log($this->err);
  2033 + return false;
  2034 + }
  2035 + }
  2036 + $skeys = array();
  2037 + $keys = array();
  2038 + foreach ($names as $name) {
  2039 + $bn = basename($name, '.key');
  2040 + if ($bn . '.key' == $name) {
  2041 + $keys[] = $bn;
  2042 + $skeys[] = "'" . $bn . "'";
  2043 + }
  2044 + }
  2045 + $res = $this->db->query("UPDATE dnssec_keys SET archive = 'yes' WHERE " .
  2046 + "dszone = " . $id . " AND " .
  2047 + "archive = 'no'");
  2048 + if (MDB2::isError($res)) {
  2049 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2050 + error_log($this->err);
  2051 + return false;
  2052 + }
  2053 + $res = $this->db->query("UPDATE dnssec_keys SET archive = 'no' WHERE " .
  2054 + "dszone = " . $id . " AND " .
  2055 + "filename IN (" . implode(",", $skeys) . ")");
  2056 + if (MDB2::isError($res)) {
  2057 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2058 + error_log($this->err);
  2059 + return false;
  2060 + }
  2061 + foreach ($keys as $keyf) {
  2062 + $res = $this->db->query("SELECT id, fkey, fprivate FROM dnssec_keys WHERE filename = '" . $keyf . "' AND dszone = " . $id . " AND archive = 'no'");
  2063 + if (MDB2::isError($res)) {
  2064 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2065 + error_log($this->err);
  2066 + return false;
  2067 + }
  2068 + $kfile = file_get_contents($zonedir . $keyf . '.key');
  2069 + $pfile = file_get_contents($zonedir . $keyf . '.private');
  2070 + if ($res->numRows() == 0) {
  2071 + $this->db->query("INSERT INTO dnssec_keys (dszone, filename, fkey, fprivate, archive) VALUES ('" . $id . "','" .
  2072 + $keyf . "', '" . $kfile . "', '" .
  2073 + $pfile . "', 'no');"
  2074 + );
  2075 + if (MDB2::isError($res)) {
  2076 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2077 + error_log($this->err);
  2078 + return false;
  2079 + }
  2080 + } else {
  2081 + $row = $res->fetchRow();
  2082 + if (($kfile != $row['fkey']) || ($pfile != $row['fprivate'])) {
  2083 + $res = $this->db->query("UPDATE dnssec_keys SET " .
  2084 + "fkey = '" . $kfile . "', " .
  2085 + "fprivate = '" . $pfile .
  2086 + "' WHERE dszone = " . $id .
  2087 + " AND filename = '" . $keyf .
  2088 + "' AND archive = 'no'"
  2089 + );
  2090 + if (MDB2::isError($res)) {
  2091 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2092 + error_log($this->err);
  2093 + return false;
  2094 + }
  2095 + }
  2096 + }
  2097 + }
  2098 + } else {
  2099 + $fh = fopen($zonedir . "dsset-" . $this->head['name'] . ".", 'w');
  2100 + fwrite($fh, $sel['dsset']);
  2101 + fclose($fh);
  2102 + $fh = fopen($zonedir . $this->head['name'] . ".krf", 'w');
  2103 + fwrite($fh, $sel['krf'] . "\n\n");
  2104 + fclose($fh);
  2105 + $id = $sel['id'];
  2106 + $res = $this->db->query("SELECT * FROM dnssec_keys WHERE " .
  2107 + " dszone = " . $id . " AND " .
  2108 + " archive = 'no'"
  2109 + );
  2110 + if (MDB2::isError($res)) {
  2111 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2112 + error_log($this->err);
  2113 + return false;
  2114 + }
  2115 + if ($res->numRows() < 3) {
  2116 + $this->err .= "Missing key records\n";
  2117 + error_log($this->err);
  2118 + return false;
  2119 + }
  2120 + while ($rec = $res->fetchRow()) {
  2121 + foreach (array('private', 'key') as $ext) {
  2122 + $fh = fopen($zonedir . $rec['filename'] . "." . $ext, 'w');
  2123 + fwrite($fh, $rec['f' . $ext] . "\n");
  2124 + fclose($fh);
  2125 + }
  2126 + }
  2127 + }
  2128 + } elseif ($filesok) {
  2129 + $dsset = '';
  2130 + $krf = '';
  2131 + $keyset = array();
  2132 + foreach ($names as $name) {
  2133 + switch ($name) {
  2134 + case 'dsset-' . $this->head['name'] . '.':
  2135 + $dsset = file_get_contents($zonedir . $name);
  2136 + break;
  2137 + case $this->head['name'] . '.krf':
  2138 + $krf = file_get_contents($zonedir . $name);
  2139 + break;
  2140 + default:
  2141 + $ext = (basename($name, '.key') == $name) ? 'private' : 'key';
  2142 + $base = basename($name, '.' . $ext);
  2143 + $keyset[$base][$ext] = file_get_contents($zonedir . $name);
  2144 + }
  2145 + }
  2146 + if (($krf == '') || ($dsset == '')) {
  2147 + $this->err .= "Incomplete DSSET\n";
  2148 + error_log($this->err);
  2149 + return false;
  2150 + } else {
  2151 + $res = $this->db->query("INSERT INTO dnssec_zones (zone, krf, dsset) VALUES ('" .
  2152 + $this->head['id'] . "', '" .
  2153 + $krf . "', '" .
  2154 + $dsset . "')"
  2155 + );
  2156 + if (MDB2::isError($res)) {
  2157 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2158 + error_log($this->err);
  2159 + return false;
  2160 + }
  2161 + $res = $this->db->query("SELECT id FROM dnssec_zones WHERE zone = " . $this->head['id']);
  2162 + if (MDB2::isError($res)) {
  2163 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2164 + error_log($this->err);
  2165 + return false;
  2166 + }
  2167 + $rec = $res->fetchRow();
  2168 + $id = $rec['id'];
  2169 + $ok = 0;
  2170 + foreach ($keyset as $name => $arr) {
  2171 + $key = $arr['key'];
  2172 + $private = $arr['private'];
  2173 + if (($key == '') || ($private == '')) {
  2174 + $this->err .= "Incomplete KEYSET\n";
  2175 + error_log($this->err);
  2176 + return false;
  2177 + }
  2178 + $res = $this->db->query("INSERT INTO dnssec_keys (dszone, filename, fkey, fprivate, archive) VALUES (" .
  2179 + $id . ", '" .
  2180 + $name . "', '" .
  2181 + $key . "', '" .
  2182 + $private . "', 'no')"
  2183 + );
  2184 + if (MDB2::isError($res)) {
  2185 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2186 + error_log($this->err);
  2187 + return false;
  2188 + }
  2189 + $ok++;
  2190 + }
  2191 + if ($ok < 3) {
  2192 + $this->err .= "Not enough KEYSET\n";
  2193 + error_log($this->err);
  2194 + return false;
  2195 + }
  2196 + }
  2197 + } else {
  2198 + return false;
  2199 + }
  2200 + return true;
  2201 + }
  2202 +
  2203 + public function doSecure($zonedir, $zonesigner, $rollinit, $rollerconf) {
  2204 + if (!$this->is_complete()) {
  2205 + ob_start();
  2206 + var_dump($this->head);
  2207 + $this->err .= "Zone head is not complete" . "\n" . ob_get_clean();
  2208 + error_log($this->err);
  2209 + return false;
  2210 + }
  2211 + $err = $this->err;
  2212 + $param = (($this->refresh_secure($zonedir)) && ($err == $this->err)) ? '' : ' -genkeys -usensec3';
  2213 + if ($err != $this->err) return false;
  2214 + $cmd = $zonesigner . $param . " -zone " . $this->head['name'] . " " . $zonedir . $this->head['name'] . " 2>/dev/stdout";
  2215 + unset($coutput);
  2216 + $currpath = getcwd();
  2217 + chdir($zonedir);
  2218 + exec($cmd, $coutput, $signexit);
  2219 + chdir($currpath);
  2220 + if ($signexit != 0) {
  2221 + $this->err .= "Zonesigner error (" . $signexit . "):\n" . implode("\n",$coutput);
  2222 + error_log($this->err);
  2223 + return false;
  2224 + } else {
  2225 + $this->msg .= "Zonesigner output (" . $signexit . "):\n " . implode("\n ",$coutput) . "\n";
  2226 + }
  2227 + if (!$this->refresh_secure($zonedir)) return false;
  2228 + $rollf = file($rollerconf, FILE_IGNORE_NEW_LINES );
  2229 + $noroll = false;
  2230 + foreach ($rollf as $row) {
  2231 + preg_match('/^\s*roll\s+"' . $this->head['name'] . '"\s*/', $row, $match);
  2232 + $noroll = (isset($match[0]) && ($row == $match[0]));
  2233 + if ($noroll) break;
  2234 + }
  2235 + if (!$noroll) {
  2236 + $cmd = $rollinit . " " . $this->head['name'] .
  2237 + " -zone " . $zonedir . $this->head['name'] . '.signed' .
  2238 + " -keyrec " . $zonedir . $this->head['name'] . ".krf " .
  2239 + " -directory " . $zonedir . " 2>/dev/stdout";
  2240 + unset($coutput);
  2241 + exec($cmd, $coutput, $exit);
  2242 + if ($exit != 0) {
  2243 + $this->err .= "Rollerd error(" . $exit . "):\n" . implode("\n ",$coutput) . "\n";
  2244 + error_log($this->err);
  2245 + return false;
  2246 + } else {
  2247 + $fh = fopen($rollerconf, "a+");
  2248 + fwrite($fh, "\n# rollinit config for zone " . hostToIdn($this->head['name']) . ":\n" . implode("\n", $coutput) . "\n");
  2249 + fclose($fh);
  2250 + $this->msg .= "\n Rollerd for zone " . hostToIdn($this->head['name']) . " is configured now\n";
  2251 + }
  2252 + } else {
  2253 + $this->msg .= "\n Rollerd for zone " . hostToIdn($this->head['name']) . " has already set\n";
  2254 + }
  2255 + return true;
  2256 + }
  2257 +
  2258 + private function is_complete() {
  2259 + return (($this->head['name'] > '') &&
  2260 + ($this->head['pri_dns'] > '') &&
  2261 + ($this->head['sec_dns'] > '') &&
  2262 + ($this->head['refresh'] > 0) &&
  2263 + ($this->head['retry'] > 0) &&
  2264 + ($this->head['expire'] > 0) &&
  2265 + ($this->head['ttl'] > 0) &&
  2266 + ($this->head['owner'] > 0));
  2267 + }
  2268 +
  2269 + public function doCommit() {
  2270 + if (!$this->is_complete()) {
  2271 + ob_start();
  2272 + var_dump($this->head);
  2273 + $this->err .= "Zone head is not complete" . "\n" . ob_get_clean();
  2274 + error_log($this->err);
  2275 + return false;
  2276 + }
  2277 + $res = $this->db->query("UPDATE zones SET " .
  2278 + "updated = 'no' " .
  2279 + "WHERE id = " . $this->head['id']);
  2280 + if (MDB2::isError($res)) {
  2281 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2282 + error_log($this->err);
  2283 + return false;
  2284 + }
  2285 + return $this->loadZoneHead();
  2286 + }
  2287 +
  2288 + public function saveZoneHead() {
  2289 + if (!$this->is_complete()) {
  2290 + ob_start();
  2291 + var_dump($this->head);
  2292 + $this->err .= "Zone head is not complete" . "\n" . ob_get_clean();
  2293 + error_log($this->err);
  2294 + return false;
  2295 + }
  2296 + if (!isset($this->head['id'])) {
  2297 + $srl =intval(date('Ymd') . '01');
  2298 + $vld = (isset($this->head['valid'])) ? $this->head['valid'] : 'may';
  2299 + $upd = 'yes';
  2300 + $res = $this->db->query("INSERT INTO zones " .
  2301 + "(name, pri_dns, sec_dns, serial, refresh, retry, expire, ttl, valid, owner, updated, secured) " .
  2302 + "VALUES ('" . $this->head['name'] .
  2303 + "', '" . $this->head['pri_dns'] .
  2304 + "', '" . $this->head['sec_dns'] .
  2305 + "', " . $srl .
  2306 + ", " . $this->head['refresh'] .
  2307 + ", " . $this->head['retry'] .
  2308 + ", " . $this->head['expire'] .
  2309 + ", " . $this->head['ttl'] .
  2310 + ", '" . $vld .
  2311 + "', " . $this->head['owner'] .
  2312 + ", '" . $upd .
  2313 + "', '" . $this->head['secured'] . "')");
  2314 + if (MDB2::isError($res)) {
  2315 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2316 + error_log($this->err);
  2317 + return false;
  2318 + }
  2319 + return $this->loadZone();
  2320 + } else {
  2321 + $srl = ($this->head['updated'] == 'no') ? intval(date('Ymd') . '01') : $this->head['serial'];
  2322 + if ($srl <= $this->head['serial']) {
  2323 + $srl = ($this->head['updated'] == 'no') ? $this->head['serial'] + 1 : $this->head['serial'];
  2324 + }
  2325 + $vld = (($this->head['valid'] == 'yes') || ($this->head['valid'] == 'no')) ? $this->head['valid'] : 'may';
  2326 + $upd = ((isset($this->head['updated'])) && ($this->head['updated'] != 'del')) ? 'yes' : $this->head['updated'];
  2327 + $res = $this->db->query("UPDATE zones SET " .
  2328 + "name = '" . $this->head['name'] . "', " .
  2329 + "pri_dns = '" . $this->head['pri_dns'] . "', " .
  2330 + "sec_dns = '" . $this->head['sec_dns'] . "', " .
  2331 + "serial = " . $srl . ", " .
  2332 + "refresh = " . $this->head['refresh'] . ", " .
  2333 + "retry = " . $this->head['retry'] . ", " .
  2334 + "expire = " . $this->head['expire'] . ", " .
  2335 + "ttl = " . $this->head['ttl'] . ", " .
  2336 + "valid = '" . $vld . "', " .
  2337 + "owner = " . $this->head['owner'] . ", " .
  2338 + "updated = '" . $upd . "', " .
  2339 + "secured = '" . $this->head['secured'] . "' " .
  2340 + "WHERE id = " . $this->head['id']);
  2341 + if (MDB2::isError($res)) {
  2342 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2343 + error_log($this->err);
  2344 + return false;
  2345 + }
  2346 + return $this->loadZoneHead();
  2347 + }
  2348 + }
  2349 +
  2350 + public function saveZone() {
  2351 + if ($this->saveZoneHead()) {
  2352 + foreach ($this->records as $each) {
  2353 + if (!$each->saveRecord()) {
  2354 + $this->err = $each->getErr();
  2355 + return false;
  2356 + }
  2357 + }
  2358 + return true;
  2359 + } else {
  2360 + return false;
  2361 + }
  2362 + }
  2363 +
  2364 + public function eraseZone() {
  2365 + if (!$this->is_identified()) {
  2366 + ob_start();
  2367 + var_dump($this->head);
  2368 + $this->err .= "Zone head is not complete" . "\n" . ob_get_clean();
  2369 + error_log($this->err);
  2370 + return false;
  2371 + } else {
  2372 + $where = ' WHERE ';
  2373 + if ($this->head['id'] >>= 0) {
  2374 + $where .= "id = " . $this->head['id'];
  2375 + } else {
  2376 + $where .= "name = '" . $this->head['name'] . "'";
  2377 + }
  2378 + $res = $this->db->query("DELETE FROM zones " . $where);
  2379 + if (MDB2::isError($res)) {
  2380 + $this->err .= $res->getMessage() . "\n" . $res->getDebugInfo();
  2381 + error_log($this->err);
  2382 + return false;
  2383 + }
  2384 + $this->clearZone();
  2385 + return true;
  2386 + }
  2387 + }
  2388 +
  2389 + public function clearZone() {
  2390 + $id = $this->head['id'];
  2391 + $head = array(
  2392 + 'id' => $id,
  2393 + 'name' => '',
  2394 + 'pri_dns' => '',
  2395 + 'sec_dns' => '',
  2396 + 'serial' => 0,
  2397 + 'refresh' => 0,
  2398 + 'retry' => 0,
  2399 + 'expire' => 0,
  2400 + 'ttl' => 0,
  2401 + 'valid' => 'may',
  2402 + 'owner' => 0,
  2403 + 'updated' => 'no',
  2404 + 'secured' => 'no',
  2405 + );
  2406 + $this->head = $head;
  2407 + $this->records = array();
  2408 + $this->isloaded = FALSE;
  2409 + }
  2410 + }
... ...
src/chpass.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * chpass.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + *********************************************************************
  23 + *
  24 + * Provides the ligin form
  25 + *
  26 + *
  27 + */
  28 +
  29 +require_once "include.php";
  30 +
  31 +$smarty->assign("pagetitle", "Change password");
  32 +$smarty->assign("template", "chpass.tpl");
  33 +$smarty->assign("help", help("chpass"));
  34 +$smarty->assign("menu_button", menu_buttons());
  35 +$smarty->display("main.tpl");
  36 +?>
... ...
src/commit.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * commit.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Applies the zone/record changes to the system
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +$dslave = array();
  31 +$dmaster = array();
  32 +
  33 +$dslave = $user->getDeletedZones('slave');
  34 +$dmaster = $user->getDeletedZones('master');
  35 +$cslave = $user->getCommitableZones('slave');
  36 +$cmaster = $user->getCommitableZones('master');
  37 +$allz = count($dmaster) + count($dslave) + count($cmaster) + count($cslave);
  38 +$done = 0;
  39 +
  40 +if (isset($_SERVER['HTTP_REFERER']) &&
  41 + (preg_replace('/https?:\/\/[^\/]+/', '', $_SERVER['HTTP_REFERER']) != $_SERVER['PHP_SELF']) &&
  42 + (!isset($_GET['commit'])) &&
  43 + ($allz >0)) {
  44 + $smarty->assign("pagetitle", "Commit changes");
  45 + $smarty->assign("template", "commit.tpl");
  46 + $smarty->assign("help", help("precommit"));
  47 + $smarty->assign("menu_button", menu_buttons());
  48 + $smarty->display("main.tpl");
  49 + die();
  50 +} elseif ((isset($_GET['commit'])) && ($_GET['commit'] != 'y')) {
  51 + problem();
  52 +} elseif (count($dmaster) +
  53 + count($dslave) +
  54 + count($cmaster) +
  55 + count($cslave) == 0) {
  56 + problem("nocommit");
  57 +}
  58 +
  59 +$bind = new bindConfig($conf->conf);
  60 +
  61 +$deleted = '';
  62 +$commited = '';
  63 +$error = '';
  64 +
  65 +$delm = (count($dmaster) > 0) ? "<strong>" . "Deleting master records" . "</strong>\n\n" : '';
  66 +
  67 +foreach ($dmaster as $master) {
  68 + $dmz = new masterZone(intval($master['id']));
  69 + $dmz->loadZoneHead();
  70 + $hd = $dmz->getZoneHead();
  71 + $hdr = $dmz->getZoneHeadRaw();
  72 + $dmz->eraseZone();
  73 + $err = $dmz->getErr();
  74 + if ($err > '') {
  75 + $error .= "<u>" . $hd['name'] . ":</u> " . "Error in deleting" . "\n" . $err . '\n\n';
  76 + } else {
  77 + $deleted .= "<u>" . $hd['name'] . ":</u> Deleting success.\n\n";
  78 + $bind->eraseConfig($hdr['name']);
  79 + $done++;
  80 + }
  81 +}
  82 +
  83 +$error = ($error > '') ? $delm . $error : '';
  84 +$deleted = ($deleted > '') ? $delm . $deleted : '';
  85 +
  86 +$errors = '';
  87 +$deleteds = '';
  88 +$delm .= (count($dslave) > 0) ? "<strong>" . "Deleting slave records" . "</strong>\n\n" : '';
  89 +$delm = ($deleted > '') ? "\n" . $delm : $delm;
  90 +
  91 +foreach ($dslave as $slave) {
  92 + $dsz = new slaveZone(intval($slave['id']));
  93 + $dsz->loadZoneHead();
  94 + $hd = $dsz->getZoneHead();
  95 + $hdr = $dsz->getZoneHeadRaw();
  96 + $dsz->eraseZone();
  97 + $err = $dsz->getErr();
  98 + if ($err > '') {
  99 + $errors .= "<u>" . $hd['name'] . ":</u> Error in deleting\n" . $err . '\n\n';
  100 + } else {
  101 + $deleteds .= "<u>" . $hd['name'] . "</u>: Deleting success.\n\n";
  102 + $bind->eraseConfig($hdr['name']);
  103 + $done++;
  104 + }
  105 +}
  106 +
  107 +$error .= ($errors > '') ? $delm . $errors : '';
  108 +$deleted .= ($deleteds > '') ? $delm . $deleteds : '';
  109 +$errors = '';
  110 +
  111 +$comm = (count($cmaster) > 0) ? "<strong>" . "Committing master records" . "</strong>\n\n" : '';
  112 +$mcomm = '';
  113 +
  114 +foreach ($cmaster as $master) {
  115 + $cmz = new masterZone(intval($master['id']));
  116 + $cmz->loadZoneHead();
  117 + $hd = $cmz->getZoneHead();
  118 + $hdr = $cmz->getZoneHeadRaw();
  119 + $cmz->writeZone($conf->path . $hdr['name'], $conf->hostMaster);
  120 + $zarray = array(
  121 + 'type' => 'master',
  122 + 'file' => $hdr['name'],
  123 + );
  124 + $zarray['file'] .= (($hd['secured'] == 'yes') && ($cmz->doSecure($conf->path, $conf->zoneSigner, $conf->rollInit, $conf->rollerConf))) ? ".signed" : "";
  125 + $cmz->doCommit();
  126 + $err = $cmz->getErr();
  127 + if ($err > '') {
  128 + $errors .= "<u>" . $hd['name'] . ":</u> Error in committing\n" . $err . '\n\n';
  129 + } else {
  130 + $mcomm .= "<u>" . $hd['name'] . "</u>: Committing success.\n" . $cmz->getMsg() . "\n";
  131 + $bind->addConfig($hdr['name'], $zarray);
  132 + $done++;
  133 + }
  134 +}
  135 +
  136 +$error .= ($errors > '') ? $comm . $errors : '';
  137 +$commited .= ($mcomm > '') ? $comm . $mcomm: '';
  138 +$errors = '';
  139 +
  140 +$comm = (count($cslave) > 0) ? "<strong>" . "Committing slave records" . "</strong>\n\n" : '';
  141 +$commited .= ($comm > '') ? "\n" : '';
  142 +$scomm = '';
  143 +
  144 +foreach ($cslave as $slave) {
  145 + $csz = new slaveZone(intval($slave['id']));
  146 + $csz->loadZoneHead();
  147 + $hd = $csz->getZoneHead();
  148 + $hdr = $csz->getZoneHeadRaw();
  149 + $err = $csz->getErr();
  150 + if ($err > '') {
  151 + $errors .= "<u>" . $hd['name'] . ":</u> Error in committing\n" . $err . '\n\n';
  152 + } else {
  153 + $csz->doCommit();
  154 + $scomm .= "<u>" . $hd['name'] . "</u>: Committing success.\n\n";
  155 + $bind->addConfig($hdr['name'], array (
  156 + 'type' => 'slave',
  157 + 'masters' => $hdr['master'],
  158 + 'file' => $hdr['name'],
  159 + ));
  160 + $done++;
  161 + }
  162 +}
  163 +
  164 +$error .= ($errors > '') ? $comm . $errors : '';
  165 +$commited .= ($scomm > '') ? $comm . $scomm : '';
  166 +$bind->saveConfig($conf->conf);
  167 +
  168 +if ($done > 0) {
  169 + $cmd = $conf->rndc . " reload 2> /dev/stdout";
  170 + unset($coutput);
  171 + exec($cmd, $coutput, $exit);
  172 + if ($exit != 0) {
  173 + $error .= "Rndc error(" . $exit . "):\n" . implode("\n", $coutput);
  174 + } else {
  175 + $multi = ($done > 1) ? "zones" : "zone";
  176 + $commited .= "<b>" . $done . " " . $multi . " has been commited and reloaded:" . "</b>\n " . implode("\n ", $coutput) . "\n";
  177 + }
  178 +} else {
  179 + $commited .= "<b>" . "There wasn't commited zone" . "</b>";
  180 +}
  181 +
  182 +$error = implode("<br />", explode("\n", $error));
  183 +
  184 +
  185 +
  186 +
  187 +
  188 +
  189 +
  190 +
  191 +//~ $currpath = getcwd();
  192 +//~ $signexit = 0;
  193 +//~ $log = "";
  194 +//~
  195 +//~ $zoneres = $dbconnect->query("SELECT * FROM zones WHERE updated = 'yes'");
  196 +//~ is_error($zoneres);
  197 +//~
  198 +//~ while($zone = $zoneres->fetchrow()) {
  199 + //~ $recordres = $dbconnect->query("SELECT * FROM records " .
  200 + //~ "WHERE zone = " . $zone[0] . " AND valid != 'no' " .
  201 + //~ "ORDER BY host, type, pri, destination");
  202 + //~ is_error($recordres);
  203 + //~ $out =
  204 +//~ "\$TTL " . $zone[8] . "
  205 +//~ @ IN SOA " . $zone[2] . ". " . $conf->hostmaster . ". (
  206 + //~ " . $zone[4] . " \t; Serial
  207 + //~ " . $zone[5] . " \t\t; Refresh
  208 + //~ " . $zone[6] . " \t\t; Retry
  209 + //~ " . $zone[7] . " \t; Expire
  210 + //~ " . $zone[8] . ")\t\t; Negative Cache TTL
  211 +//~ ;\n" ;
  212 + //~ if ($zone[2] != '') {
  213 + //~ $out .= prettyer("@",'','NS','',$zone[2] . ".") . "\n";
  214 + //~ }
  215 + //~ if ($zone[3] != '') {
  216 + //~ $out .= prettyer("@",'','NS','',$zone[3] . ".") . "\n";
  217 + //~ }
  218 + //~ $fd = fopen($conf->path . preg_replace('/\//','-',$zone[1]), "w")
  219 + //~ or die("Cannot open: " . $conf->path . preg_replace('/\//','-',$zone[1]));
  220 + //~ fwrite($fd, $out);
  221 +//~
  222 + //~ while($record = $recordres->fetchrow()) {
  223 + //~ if($record[3] == "MX") {
  224 + //~ $pri = $record[4];
  225 + //~ }
  226 + //~ else {
  227 + //~ $pri = "";
  228 + //~ }
  229 + //~ if(($record[7] == NULL) || ($record[7] == 0)){ $record[7]=''; }
  230 + //~ if(
  231 + //~ ($record[3] == "NS" ||
  232 + //~ $record[3] == "PTR" ||
  233 + //~ $record[3] == "CNAME" ||
  234 + //~ $record[3] == "MX" ||
  235 + //~ $record[3] == "SRV") &&
  236 + //~ ($record[5] != "@")) {
  237 + //~ $destination = $record[5] . ".";
  238 + //~ }
  239 + //~ else {
  240 + //~ $destination = $record[5];
  241 + //~ }
  242 + //~ $out = prettyer($record[2],$record[7],$record[3],$pri,$destination) . "\n";
  243 + //~ fwrite($fd, $out);
  244 + //~ }
  245 + //~ fclose($fd);
  246 +//~
  247 + //~ // Check the full zone only
  248 + //~ $cmd = $conf->namedcheckzone . " " . $zone[1] . " " . $_CONF['path'] . preg_replace('/\//','-',$zone[1]) . " 2>/dev/stdout";
  249 + //~ unset($coutput);
  250 + //~ exec($cmd, $coutput, $exit);
  251 + //~ $log = "<big><u>Master zones</u>\n<b>" . idn2host($zone[1]) . " (SEC: $zone[12]) output:</b></big>\n";
  252 + //~ $log .= "<b> Zonecheck:</b>\n";
  253 + //~ $loglevel=LOG_INFO;
  254 + //~ // Log the output
  255 + //~ openlog('CHECKZONE', LOG_PID, LOG_SYSLOG);
  256 + //~ if ($exit != 0) {
  257 + //~ $loglevel=LOG_ERR;
  258 + //~ }
  259 + //~ syslog($loglevel, "Exitcode: $exit");
  260 + //~ $log .= " <b>Exitcode:</b> $exit\n";
  261 + //~ foreach ($coutput as $line) {
  262 + //~ syslog($loglevel, $line);
  263 + //~ $log .= " $line\n";
  264 + //~ }
  265 + //~ closelog();
  266 +//~
  267 + //~ if ($exit == 0) {
  268 + //~ $updateres = $dbconnect->query("UPDATE zones SET updated = 'no', valid = 'yes' " .
  269 + //~ "WHERE id = " . $zone[0]);
  270 + //~ is_error($updateres);
  271 + //~ $testres = $dbconnect->query("UPDATE records SET valid = 'yes' " .
  272 + //~ "WHERE zone = " . $zone[0]);
  273 + //~ is_error($testres);
  274 + //~ $rebuild = "yes";
  275 + //~ $zonefile = $conf->path . preg_replace('/\//','-',$zone[1]);
  276 + //~ if ($zone[12] == "yes") {
  277 + //~ chdir($conf->path);
  278 + //~ $cmd = '';
  279 + //~ if (file_exists($zonefile . '.signed')) {
  280 + //~ $cmd = $conf->zonesigner . " -zone " . $zone[1] . " " . $zonefile . " 2>/dev/stdout";
  281 + //~ } else {
  282 + //~ $cmd = $conf->zonesigner . " -genkeys -usensec3 -zone " . $zone[1] . " " . $zonefile . " 2>/dev/stdout";
  283 + //~ }
  284 + //~ unset($coutput);
  285 + //~ exec($cmd, $coutput, $signexit);
  286 + //~ $loglevel=LOG_INFO;
  287 + //~ openlog('DNSSEC', LOG_PID, LOG_SYSLOG);
  288 + //~ if ($signexit != 0) {
  289 + //~ $loglevel=LOG_ERR;
  290 + //~ }
  291 + //~ syslog($loglevel, "Exitcode: $signexit");
  292 + //~ $log .= "<b> Zonesign:</b>\n";
  293 + //~ $log .= " <b>Exitcode:</b> $signexit\n";
  294 + //~ foreach ($coutput as $line) {
  295 + //~ syslog($loglevel, $line);
  296 + //~ $log .= " $line\n";
  297 + //~ }
  298 + //~ closelog();
  299 + //~ chdir($currpath);
  300 + //~ if($signexit == 0) {
  301 +//~
  302 + //~ // Check the signed zone again
  303 + //~ $cmd = $conf->namedcheckzone . " " . $zone[1] . " " . $_CONF['path'] . preg_replace('/\//','-',$zone[1]) . ".signed 2>/dev/stdout";
  304 + //~ unset($coutput);
  305 + //~ exec($cmd, $coutput, $exit);
  306 + //~ $loglevel=LOG_INFO;
  307 + //~ // Log the output
  308 + //~ $log .= " <b>Zonecheck(signed):</b>\n";
  309 + //~ openlog('CHECKZONE', LOG_PID, LOG_SYSLOG);
  310 + //~ if ($exit != 0) {
  311 + //~ $loglevel=LOG_ERR;
  312 + //~ }
  313 + //~ syslog($loglevel, "Exitcode: $exit");
  314 + //~ $log .= " <b>Exitcode:</b> $exit\n";
  315 + //~ foreach ($coutput as $line) {
  316 + //~ syslog($loglevel, $line);
  317 + //~ $log .= " $line\n";
  318 + //~ }
  319 + //~ closelog();
  320 +//~
  321 + //~ $zonefile .= ".signed";
  322 + //~ }
  323 + //~ }
  324 + //~ }
  325 + //~ else {
  326 + //~ $updateres = $dbconnect->query("UPDATE zones SET updated = 'yes', valid = 'no' " .
  327 + //~ "WHERE id = " . $zone[0]);
  328 + //~ is_error($updateres);
  329 + //~ $testres = $dbconnect->query("UPDATE records SET valid = 'no' " .
  330 + //~ "WHERE zone = " . $zone[0]);
  331 + //~ is_error($testres);
  332 + //~ }
  333 +//~ }
  334 +//~
  335 +//~ $fd = fopen($conf->slave_conf, "w");
  336 +//~ fwrite($fd, "// Slave zones\n\n");
  337 +//~
  338 +//~ $confres = $dbconnect->query("SELECT name, master, updated FROM slave_zones where name <> 'DUMMY' ORDER BY name");
  339 +//~ is_error($confres);
  340 +//~
  341 +//~ while($conf = $confres->fetchrow()) {
  342 + //~ $cout = "zone \"" . $conf[0] . "\" {\n\t" .
  343 + //~ "type slave;\n\t" .
  344 + //~ "masters {" . $conf[1] . ";};\n\t" .
  345 + //~ "file \"" . preg_replace('/\//','-',$conf[0]) . "\";\n};\n\n";
  346 + //~ fwrite($fd, $cout);
  347 + //~ $updateres = $dbconnect->query("UPDATE slave_zones SET updated = 'no', valid = 'yes' " .
  348 + //~ "WHERE name = \"" . $conf[0] . "\"");
  349 + //~ is_error($updateres);
  350 + //~ if($conf[2] == 'yes'){ $rebuild = "yes";}
  351 +//~ }
  352 +//~
  353 +//~ $res = $dbconnect->query("SELECT updated " .
  354 + //~ "FROM slave_zones " .
  355 + //~ "WHERE name = 'DUMMY'");
  356 +//~ $row = $res->fetchrow();
  357 +//~ if($row[0] == "yes"){ $rebuild = "yes";}
  358 +//~
  359 +//~ $updateres = $dbconnect->query("UPDATE slave_zones SET updated = 'no', valid = 'unknown' " .
  360 + //~ "WHERE name = 'DUMMY'");
  361 +//~ is_error($updateres);
  362 +//~
  363 +//~ fclose($fd);
  364 +//~
  365 +//~ if (isset($rebuild)) {
  366 + //~ $log .= "<big><b>Config rebuild output</b></big>\n";
  367 + //~ $confres = $dbconnect->query("SELECT name, secured FROM zones ORDER BY name");
  368 + //~ is_error($confres);
  369 + //~ $cout = "// Master zones\n\n";
  370 + //~ while($conf = $confres->fetchrow()) {
  371 + //~ $zonefile = preg_replace('/\//','-',$conf[0]);
  372 + //~ $signed = $zonefile . '.signed';
  373 + //~ if(($conf[1] == "yes") && (file_exists($conf->path . $signed))) {
  374 + //~ $log .= " <big>" . host2idn($zonefile) . " rolling</big>\n";
  375 + //~ $search = "roll\t\"$zonefile\"";
  376 + //~ $exists = false;
  377 + //~ $lines = file($conf->rollerconf);
  378 + //~ while (list($key, $line) = each($lines) and !$exists) {
  379 + //~ $exists = (strpos($line, $search) !== FALSE);
  380 + //~ }
  381 + //~ if (!$exists) {
  382 + //~ unset($coutput);
  383 + //~ $cmd = $conf->rollinit . " " . $zonefile . " -zone " . $_CONF['path'] . $signed . " -keyrec " . $_CONF['path'] . $zonefile . ".krf -directory " . $_CONF['path'] . " 2>/dev/stdout";
  384 + //~ exec($cmd, $coutput, $exit);
  385 + //~ $loglevel=LOG_INFO;
  386 + //~ $log .= " <b> Rollerconfig:</b>\n";
  387 + //~ // Log the output
  388 + //~ openlog('ROLLERCONF', LOG_PID, LOG_SYSLOG);
  389 + //~ if ($exit != 0) {
  390 + //~ $loglevel=LOG_ERR;
  391 + //~ }
  392 + //~ syslog($loglevel, "Exitcode: $exit");
  393 + //~ $log .= " <b>Exitcode:</b> $exit\n";
  394 + //~ $roll = "";
  395 + //~ foreach ($coutput as $line) {
  396 + //~ syslog($loglevel, $line);
  397 + //~ $roll .= "$line\n";
  398 + //~ $log .= " $linr\n";
  399 + //~ }
  400 + //~ $fd = fopen($conf->rollerconf,"a+");
  401 + //~ fwrite($fd, $roll);
  402 + //~ fclose($fd);
  403 + //~ } else {
  404 + //~ $log .= " <b> Rollerconfig exists</b>\n";
  405 + //~ }
  406 + //~ $zonefile = $signed;
  407 + //~ }
  408 + //~ $cout .= "zone \"" . $conf[0] . "\" {\n\ttype master;\n\tfile \"" . $zonefile . "\";\n};\n\n";
  409 + //~ }
  410 + //~ $fd = fopen($conf->conf,"w");
  411 + //~ fwrite($fd, $cout);
  412 + //~ fclose($fd);
  413 +//~
  414 + //~ // Check the master config
  415 + //~ $cmd = $conf->namedcheckconf . " " . $_CONF['conf'] . " 2> /dev/stdout";
  416 + //~ unset($coutput);
  417 + //~ exec($cmd, $coutput, $exit);
  418 + //~ $loglevel=LOG_INFO;
  419 + //~ $log .= " <b>Master configcheck:</b>\n";
  420 + //~ // Log the output
  421 + //~ openlog('CHECKCONF', LOG_PID, LOG_SYSLOG);
  422 + //~ if ($exit != 0) {
  423 + //~ $loglevel=LOG_ERR;
  424 + //~ }
  425 + //~ syslog($loglevel, "Exitcode: $exit");
  426 + //~ $log .= " <b>Exitcode:</b> $exit\n";
  427 + //~ foreach ($coutput as $line) {
  428 + //~ syslog($loglevel, $line);
  429 + //~ $log .= " $line\n";
  430 + //~ }
  431 + //~ closelog();
  432 +//~
  433 + //~ // Check the slave config
  434 + //~ $cmd = $conf->namedcheckconf . " " . $_CONF['slave_conf'] . " 2> /dev/stdout";
  435 + //~ unset($coutput);
  436 + //~ exec($cmd, $coutput, $slave_exit);
  437 + //~ $loglevel=LOG_INFO;
  438 + //~ $log .= " <b>Slave configcheck:</b>\n";
  439 + //~ // Log the output
  440 + //~ openlog('CHECKCONF', LOG_PID, LOG_SYSLOG);
  441 + //~ if ($slave_exit != 0) {
  442 + //~ $loglevel=LOG_ERR;
  443 + //~ $updateres = $dbconnect->query("UPDATE slave_zones SET updated = 'yes', valid = 'no' " .
  444 + //~ "WHERE name = 'DUMMY'");
  445 + //~ is_error($updateres);
  446 + //~ } else {
  447 + //~ $updateres = $dbconnect->query("UPDATE slave_zones SET updated = 'no', valid = 'yes' " .
  448 + //~ "WHERE name = 'DUMMY'");
  449 + //~ is_error($updateres);
  450 + //~ }
  451 + //~ syslog($loglevel, "Exitcode: $slave_exit");
  452 + //~ $log .= " <b>Exitcode:</b> $slave_exit\n";
  453 + //~ foreach ($coutput as $line) {
  454 + //~ syslog($loglevel, $line);
  455 + //~ $log .= " $line\n";
  456 + //~ }
  457 + //~ closelog();
  458 + //~ $exit += $slave_exit;
  459 +//~
  460 + //~ if ($exit == 0) {
  461 +//~
  462 + //~ // Reaload zones
  463 + //~ $cmd = $conf->rndc . " reload 2> /dev/stdout";
  464 + //~ unset($coutput);
  465 + //~ exec($cmd, $coutput, $exit);
  466 + //~ $loglevel=LOG_INFO;
  467 + //~ $log .= " <b>Reload zones:</b>\n";
  468 + //~ // Log the output
  469 + //~ openlog('DNS reload', LOG_PID, LOG_SYSLOG);
  470 + //~ if ($exit != 0) {
  471 + //~ $loglevel=LOG_ERR;
  472 + //~ }
  473 + //~ syslog($loglevel, "Exitcode: $exit");
  474 + //~ $log .= " <b>Exitcode:</b> $exit\n";
  475 + //~ foreach ($coutput as $line) {
  476 + //~ syslog($loglevel, $line);
  477 + //~ $log .= " $line\n";
  478 + //~ }
  479 + //~ closelog();
  480 + //~ }
  481 +//~ }
  482 +//~
  483 +$smarty->assign("popuperror", $error);
  484 +$smarty->assign("success", $deleted . $commited);
  485 +$smarty->assign("pagetitle", "Commit changes");
  486 +$smarty->assign("template", "commitdone.tpl");
  487 +$smarty->assign("help", help("commit"));
  488 +$smarty->assign("menu_button", menu_buttons());
  489 +$smarty->display("main.tpl");
  490 +?>
... ...
src/convert.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * convert.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + *********************************************************************
  23 + *
  24 + * Processes the inport form and do the import.
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +$out = array();
  31 +
  32 +if($user->isAdmin()) {
  33 + if(($_SERVER['REQUEST_METHOD'] == 'POST') && (isset($_POST['method']))) {
  34 + $method = $_POST['method'];
  35 + $valid = true;
  36 + $problem = '';
  37 + $zone = '';
  38 + $content = array();
  39 + $temp = '';
  40 + switch ($method) {
  41 + case "file":
  42 + $zone = ((isset($_POST['fil_domain'])) && (isset($_FILES['fil']['tmp_name']))) ? $zone = $_POST['fil_domain'] : '';
  43 + $content = ($zone > '') ? file($_FILES['fil']['tmp_name']) :array();
  44 + $smarty->assign("method", "Upload from file");
  45 + break;
  46 + case "list":
  47 + $zone = ((isset($_POST['sel_domain'])) && ($_POST['sel'] != '- select file -')) ? $_POST['sel_domain'] : '';
  48 + $content = ($zone > '') ? file($conf->path . idnToHost($_POST['sel'])) : array();
  49 + $smarty->assign("method", "Select orphan file from list");
  50 + break;
  51 + case "text":
  52 + $zone = ((isset($_POST['txt_domain'])) && (isset($_POST['txt']))) ? $_POST['txt_domain'] : '';
  53 + $content = ($zone > '') ? explode("\n", $_POST['txt']) : array();
  54 + $smarty->assign("method", "Write zone manually or pasted from clipboard");
  55 + break;
  56 + default:
  57 + problem();
  58 + }
  59 + if (count($content) < 4) {
  60 + problem("nocontent");
  61 + }
  62 + $gzone = $zone;
  63 + $zone = hostToIdn($zone);
  64 + if ($method != 'list') {
  65 + $temp = tempnam($conf->tmp_path, "$zone");
  66 + $fh = fopen($temp, "w");
  67 + fwrite($fh, implode("\n", $content));
  68 + fclose($fh);
  69 + $check = checkZoneFile($temp, $zone);
  70 + unlink($temp);
  71 + if (!$check) {
  72 + problem("nocontent");
  73 + }
  74 + }
  75 + $mz = new masterZone($gzone);
  76 + $sz = new slaveZone($gzone);
  77 + if (($mz->loadZoneHead()) || ($sz->loadZoneHead())) {
  78 + $mz = array();
  79 + $sz = array();
  80 + problem("existzone");
  81 + }
  82 + $smarty->assign("zone", $gzone);
  83 + $nz = new masterZone();
  84 + if (($nz->parseZone($content, $zone, $user->getId())) && ($nz->getId() > 0)) {
  85 + $smarty->assign("pagetitle", "Review imported records");
  86 + $smarty->assign("template", "uploadreview.tpl");
  87 + $smarty->assign("output", explode("\n", $nz->getConf($conf->hostMaster)));
  88 + $smarty->assign("help", help("uploadreview"));
  89 + $smarty->assign("menu_button", menu_buttons());
  90 + } else {
  91 + $smarty->assign("problem", explode("\n", $nz->getErr()));
  92 + $smarty->assign("pagetitle", "Import error");
  93 + $smarty->assign("template", "uploadproblem.tpl");
  94 + $smarty->assign("help", help("uploadproblem"));
  95 + $smarty->assign("menu_button", menu_buttons());
  96 + }
  97 + $smarty->display("main.tpl");
  98 + } else {
  99 + problem();
  100 + }
  101 +} else {
  102 + access_denied();
  103 +}
  104 +?>
... ...
src/deleteuser.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * deleteuser.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + *********************************************************************
  23 + *
  24 + * Check what need to delete and provides info for confirmation
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +if($user->isAdmin()) {
  31 + $num = intval($_GET['i']);
  32 + switch ($num) {
  33 + case 0:
  34 + case 1:
  35 + problem("deleteadmin");
  36 + break;
  37 + case $user->getId();
  38 + problem("deleteys");
  39 + break;
  40 + default:
  41 + $smarty->assign("pagetitle", "Delete user");
  42 + $duser = new User($num);
  43 + $smarty->assign("user", $duser->getUser());
  44 + $smarty->assign("template", "deleteuser.tpl");
  45 + $smarty->assign("help", help("deleteuser"));
  46 + $smarty->assign("menu_button", menu_buttons());
  47 + $smarty->display("main.tpl");
  48 + }
  49 +} else {
  50 + access_denied();
  51 +}
  52 +?>
... ...
src/deletezone.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * deletezone.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + *
  23 + **********************************************************************
  24 + *
  25 + * Check what need to delete and provides info for confirmation
  26 + *
  27 + */
  28 +
  29 +require_once "include.php";
  30 +
  31 +$zoneid = intval($_GET['i']);
  32 +
  33 +if ($zoneid > 0) {
  34 + if ($user->isOwned($zoneid, 'master')) {
  35 + $smarty->assign("pagetitle", "Delete master zone");
  36 + $zone = new masterZone($zoneid);
  37 + $zone->loadZoneHead();
  38 + $res = $zone->getZoneHead();
  39 + $smarty->assign("zone", $res['name']);
  40 + $smarty->assign("zoneid", $zoneid);
  41 + $smarty->assign("template", "deletezone.tpl");
  42 + $smarty->assign("help", help("deletezone"));
  43 + $smarty->assign("menu_button", menu_buttons());
  44 + $smarty->display("main.tpl");
  45 + } else {
  46 + problem('notown');
  47 + }
  48 +} else {
  49 + problem();
  50 +}
  51 +
  52 +?>
... ...
src/end.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * end.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Destroy the session
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +$session->destroy();
  31 +die();
  32 +
  33 +?>
... ...
src/include.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * include.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Contains the main definitions, functions and elements
  25 + *
  26 + */
  27 +
  28 +$base = preg_replace('/(\/src\/([^\/]+\.php)).*/', '/', $_SERVER['REQUEST_URI']);
  29 +$src = $base . 'src/';
  30 +$config = 'config/config.php';
  31 +$lib = 'lib/';
  32 +
  33 +if (stripos($_SERVER['REQUEST_URI'], '/src/')) {
  34 + $config = '../' . $config;
  35 + $lib = '../' . $lib;
  36 +}
  37 +
  38 +set_include_path(get_include_path() . ":" . $lib);
  39 +require_once("smbind.class.php");
  40 +$conf = new Configuration($config);
  41 +$session = new Session();
  42 +
  43 +if ($conf->ReCaptcha == "yes") {
  44 + require_once("recaptchalib.php");
  45 +}
  46 +
  47 +set_include_path(get_include_path() . ":" . $conf->Smarty_Path);
  48 +
  49 +header("Content-Type: text/html; charset=UTF-8");
  50 +header("X-Content-Security-Policy: default-src 'self'; script-src 'self' self www.gstatic.com www.google.com google.com; img-src 'self' data: www.gstatic.com www.google.com google.com; style-src 'self'; font-src 'self'; frame-src 'self'; connect-src 'self' apis.google.com; object-src 'self'");
  51 +
  52 +$dbconnect = &$db;
  53 +
  54 +if (MDB2::isError($dbconnect)) {
  55 + die("Database error: " . MDB2::errorMessage($dbconnect));
  56 +} else {
  57 + $dbconnect->setFetchMode(MDB2_FETCHMODE_ASSOC);
  58 +}
  59 +
  60 +require_once("Smarty.class.php");
  61 +$smarty = new Smarty;
  62 +$smarty->assign('TITLE',$var = $conf->Title);
  63 +$smarty->assign('footerleft',$conf->Footer);
  64 +$smarty->assign('footerright',$conf->Marker);
  65 +$smarty->assign('sdomain',$conf->StaticDomain);
  66 +$smarty->assign('skin',$conf->Template);
  67 +$smarty->template_dir = $conf->Smbind_Ng . "templates";
  68 +$smarty->compile_dir = $conf->Smbind_Ng . "templates_c";
  69 +$smarty->assign("base", $base);
  70 +$smarty->assign("static", $base . "static/");
  71 +$smarty->assign("src", $src);
  72 +$smarty->assign("captcha","no");
  73 +$smarty->assign("recaptcha","");
  74 +$smarty->assign("menu_button","");
  75 +$smarty->assign("donotcommit","no");
  76 +$smarty->assign('popuperror',NULL);
  77 +
  78 +$cap_rsp = NULL;
  79 +if(isset($_POST["recaptcha_response_field"])){
  80 + if ($_POST["recaptcha_response_field"]!=''){
  81 + $rsp = recaptcha_check_answer (
  82 + $conf->RC_PrivKey,
  83 + $_SERVER["REMOTE_ADDR"],
  84 + $_POST["recaptcha_challenge_field"],
  85 + $_POST["recaptcha_response_field"]
  86 + );
  87 + if(!$rsp->is_valid) {
  88 + $cap_rsp = $rsp->error;
  89 + }
  90 + } else {
  91 + $cap_rsp = 'incorrect-captcha-sol';
  92 + }
  93 +}
  94 +
  95 +if (isset($_POST['username']) && isset($_POST['password']) && ($cap_rsp == NULL)) {
  96 + $session->login($_POST['username'], $_POST['password']);
  97 +}
  98 +
  99 +$user = new User();
  100 +$smarty->assign("loggedinuser",$user->getFullName());
  101 +
  102 +if ($user->getId() == 0) {
  103 + login_page($smarty);
  104 +}
  105 +
  106 +if ((isset($_SERVER['PHP_SELF'])) && (basename($_SERVER['PHP_SELF']) != 'index.php')) {
  107 + $smarty->assign("menu_current", $src . basename($_SERVER['PHP_SELF']));
  108 +} else {
  109 + $smarty->assign("menu_current", $base);
  110 +}
  111 +
  112 +if($user->isAdmin()) {
  113 + $smarty->assign("admin", "yes");
  114 +} else {
  115 + $smarty->assign("admin", "no");
  116 +}
  117 +
  118 +/*
  119 + *
  120 + * name: debug
  121 + * @param variable type a count of parameters for dumping it to the
  122 + * error_log
  123 + *
  124 + * @return <empty>
  125 + *
  126 + */
  127 +function debug() {
  128 + for($i = 0 ; $i < func_num_args(); $i++) {
  129 + $param = func_get_arg($i);
  130 + $dump = '';
  131 + if ((is_array($param)) || (is_object($param))) {
  132 + ob_start();
  133 + if (is_object($param)) {
  134 + $phpv = explode('.', phpversion());
  135 + if (intval($phpv[0] . $phpv[1]) < 56) {
  136 + var_dump($param->__debugInfo());
  137 + } else {
  138 + var_dump($param);
  139 + }
  140 + } else {
  141 + var_dump($param);
  142 + }
  143 + $dump .= ob_get_clean();
  144 + } else {
  145 + $dump .= $param;
  146 + }
  147 + $bt = debug_backtrace();
  148 + error_log($bt[0]['file'] . "(" . $bt[0]['line'] . "):\n" . $dump);
  149 + }
  150 +}
  151 +
  152 +/*
  153 + *
  154 + * name: makePart
  155 + *
  156 + * Creates paging feature
  157 + *
  158 + * @param
  159 + * $all -> lentgt of the listed elements
  160 + * $page -> actual page count
  161 + *
  162 + * @return range for this page
  163 + *
  164 + */
  165 +function makePart($all, $page) {
  166 + global $smarty;
  167 + global $conf;
  168 + $from = 0;
  169 + $to = $all;
  170 + $pages = 0;
  171 + $max = 0;
  172 + if ($conf->isExists('range')) {
  173 + $max = $conf->Range;
  174 + }
  175 + if ($max > 0) {
  176 + $pages = (int)($all/$max);
  177 + $mod = $all % $max;
  178 + if ($mod > 0) {
  179 + $pages++;
  180 + }
  181 + if ($pages < $page) {
  182 + $page = $pages;
  183 + }
  184 + $from = ($page-1) * $max;
  185 + $to = $from;
  186 + if (($page == $pages) && ($mod > 0)) {
  187 + $to += $mod;
  188 + } else {
  189 + $to += $max;
  190 + }
  191 + $from = ($from < 0) ? 0 : $from;
  192 + }
  193 + $pagelist = array();
  194 + for ($i=1;$i<=$pages;$i++) {
  195 + $pagelist[] = $i;
  196 + }
  197 + $pagelist = (sizeof($pagelist) > 1) ? $pagelist : NULL;
  198 + $smarty->assign("current_page", $page);
  199 + $smarty->assign("pages", $pagelist);
  200 + return array($from, $to);
  201 +}
  202 +
  203 +/*
  204 + *
  205 + * name: rndc_status
  206 + * @param no
  207 + * @return the status of rndc command
  208 + *
  209 + */
  210 +function rndc_status() {
  211 + global $conf;
  212 + $cmd = $conf->Rndc . " status > /dev/null";
  213 + system($cmd, $exit);
  214 + return $exit;
  215 +}
  216 +
  217 +/*
  218 + *
  219 + * name: logout
  220 + * @param no
  221 + * @return no
  222 + *
  223 + * Displays the logout page and destroy the http session
  224 + *
  225 + */
  226 +function logout() {
  227 + global $smarty;
  228 + global $session;
  229 + $session->destroy();
  230 + $smarty->assign("menu_button", array());
  231 + $smarty->assign("pagetitle", "Logout");
  232 + $smarty->assign("template", "logout.tpl");
  233 + $smarty->assign("help", help("logout"));
  234 + $smarty->display("main.tpl");
  235 +}
  236 +
  237 +/*
  238 + *
  239 + * name: login_page
  240 + * @param Smarty object
  241 + * @return no
  242 + *
  243 + * Checks the captcha requirements and provides the login page
  244 + *
  245 + */
  246 +function login_page($smarty) {
  247 + global $cap_rsp;
  248 + global $base;
  249 + global $conf;
  250 +
  251 + if($conf->ReCaptcha == "yes") {
  252 + $nocap = false;
  253 + foreach ($conf->NoCaptcha as $ip) {
  254 + $nocap = ($nocap or ($ip == $_SERVER['REMOTE_ADDR']));
  255 + }
  256 + if(!$nocap) {
  257 + $smarty->assign("captcha","yes");
  258 + $smarty->assign("recaptcha",recaptcha_get_html($conf->Rc_Pubkey,$cap_rsp,true));
  259 + }
  260 + }
  261 + $smarty->assign("action", $base);
  262 + $smarty->assign("pagetitle", "Login");
  263 + $smarty->assign("template", "login.tpl");
  264 + $smarty->assign("help", help("login"));
  265 + $smarty->display("main.tpl");
  266 + die();
  267 +}
  268 +
  269 +/*
  270 + *
  271 + * name: problem
  272 + * @param
  273 + * $reason -> short tag for the problem
  274 + * $title -> header title
  275 + *
  276 + * @return no
  277 + *
  278 + * Provides a kind of error page
  279 + *
  280 + */
  281 +function problem($reason = NULL, $title = NULL) {
  282 + global $smarty;
  283 + $tit = (isset($title)) ? $title : title($reason);
  284 + $smarty->assign("pagetitle", $tit);
  285 + $smarty->assign("template", "accessdenied.tpl");
  286 + $smarty->assign("reason", reason($reason));
  287 + $smarty->assign("help", help("accessdenied"));
  288 + $smarty->assign("menu_button", menu_buttons());
  289 + $smarty->display("main.tpl");
  290 + die();
  291 +}
  292 +
  293 +/*
  294 + *
  295 + * name: access_denied
  296 + * @param no
  297 + * @return no
  298 + *
  299 + * Generates the access denied problem
  300 + *
  301 + */
  302 +function access_denied() {
  303 + problem("notadmin");
  304 +}
  305 +
  306 +/*
  307 + *
  308 + * name: reason
  309 + * @param optional
  310 + * $reason -> short tag of the problem
  311 + *
  312 + * @return description string
  313 + *
  314 + * Generates description string for the known reason
  315 + *
  316 + */
  317 +function reason($reason = '') {
  318 + switch ($reason) {
  319 + case "notown":
  320 + return "You don't own this zone.";
  321 + case "unauth":
  322 + return "You are not authorized for this procedure";
  323 + case "notadmin":
  324 + return "You are not an administrator.";
  325 + case "noslave":
  326 + return "The slave zone hasn't replicated yet. Try again later.";
  327 + case "existzone":
  328 + return "The zone already exists in the database.";
  329 + case "existfile":
  330 + return "The zonefile already exists on the system.";
  331 + case "existuser":
  332 + return "The user already exists in the database.";
  333 + case "nozonename":
  334 + return "That's not much of a zone name.";
  335 + case "deleteadmin":
  336 + return "You may not delete the default admin user.";
  337 + case "deleteys":
  338 + return "You may not delete yourself.";
  339 + case "nocontent":
  340 + return "The given content empty or invalid.";
  341 + case "nocommit":
  342 + return "There is no commitable content.";
  343 + default:
  344 + return "Unknown error. Please it report to your administrator";
  345 + }
  346 +}
  347 +
  348 +/*
  349 + *
  350 + * name: title
  351 + * @param optional
  352 + * $reason -> short tag of the problem
  353 + *
  354 + * @return title string
  355 + *
  356 + * Generates title string for the known reason
  357 + *
  358 + */
  359 + function title($reason = '') {
  360 + switch ($reason) {
  361 + case "notown":
  362 + case "notadmin":
  363 + case "deleteadmin":
  364 + case "deleteys":
  365 + case "unauth":
  366 + return "Access denied";
  367 + case "noslave":
  368 + case "nocontent":
  369 + return "No data";
  370 + case "nocommit":
  371 + case "existzone":
  372 + case "existfile":
  373 + case "existuser":
  374 + case "nozonename":
  375 + return "Error in process";
  376 + default:
  377 + return "Something wrong happened";
  378 + }
  379 +}
  380 +
  381 +/*
  382 + *
  383 + * name: help
  384 + * @param
  385 + * $help tag for the info footer
  386 + *
  387 + * @return the info footer
  388 + *
  389 + * Generates the info footer
  390 + *
  391 + */
  392 +function help($help) {
  393 + switch ($help) {
  394 + case "login":
  395 + return "Please log in.";
  396 + case "mainpage":
  397 + return "User status and Server status are displayed, along with any zone informations.";
  398 + case "zoneview":
  399 + return "Your zone is dumped. Here you can view the zone in bind syntax.<small><br />" .
  400 + "<span class=attention>You cannot edit the zonefile directly!</span></small>";
  401 + case "zonepview":
  402 + return "Your zone will look like as above. You can view it in bind syntax.<small><br />" .
  403 + "<span class=attention>This zone hasn't commited yet!</span></small>";
  404 + case "zoneread":
  405 + return "Your zones are displayed. Here you can create a zone, edit a zone, view a zone, or delete a zone.";
  406 + case "newzone":
  407 + return "Enter your new zone's domain name, name servers and smbind-ng owner. " .
  408 + "This will create a new zone with a SOA and NS record.<small><br />" .
  409 + "The Web/Mail/FTP fields will create these A, CNAME, and MX template records for you. " .
  410 + "Otherwise, leave them blank.<br />In these fields you can use IP addresses or hostnames too. In this case you need to take care of the trailing dots.</small>";
  411 + case "newslavezone":
  412 + return "Enter your new slave zone's domain name, address of the master server and smbind-ng owner.";
  413 + case "recordread":
  414 + return "Here you can modify your zone's SOA record, or add, edit, or delete resource records.";
  415 + case "userlistread":
  416 + return "Here you can add, edit, or delete smbind-ng users.";
  417 + case "commit":
  418 + return "Your zone files are commited to disk, error checked, and reloaded.";
  419 + case "precommit":
  420 + return "Your modifications will be applied to the system, and the related services will notified about the changes.";
  421 + case "optionsread":
  422 + return "Here you can change options that define how smbind-ng works.";
  423 + case "deletezone":
  424 + return "Please confirm.";
  425 + case "uploadreview":
  426 + return "Please confirm your uploaded data. Some records may be missig basad on your handled record-type options";
  427 + case "uploadproblem":
  428 + return "Please fix the errors. The file output of namedcheckzone has errors.";
  429 + case "upload":
  430 + return "Here you can import a zone what is in legal bind zonefile format. Choose import method!" .
  431 + " Available methods:<small><br /><strong>Orphan files:</strong>(maybe disabled) Some file in" .
  432 + " your config directory without database records. <strong>Browse:</strong> Zone file upload" .
  433 + " from your computer. <strong>Edit:</strong> Paste contents into the box from your clipboard.</small>";
  434 + case "deleteuser":
  435 + return "Please confirm.";
  436 + case "newuser":
  437 + return "Here can you add a new user.<br />" .
  438 + "<span class=attention>Password requirements:</span> You must use letters (both upper- and lowercase), numbers and symols. Minimum length is 8 characters. " .
  439 + "10 charachers length, and using more uppercase letters and numbers is recommended.";
  440 + case "userread":
  441 + return "Here can you change the user's properties. If you don't want to change the password, leave it empty." .
  442 + "<br /><span class=attention>Password requirements:</span> You must use letters (both upper- and lowercase), numbers and symols. Minimum length is 8 characters. " .
  443 + "10 charachers length, and using more uppercase letters and numbers is recommended.";
  444 + case "chpass":
  445 + return "Here can you change your password. <small>You need to give your current password before the new!</small><br />" .
  446 + "<span class=attention>Password requirements:</span> You must use letters (both upper- and lowercase), numbers and symols. Minimum length is 8 characters. " .
  447 + "10 charachers length, and using more uppercase letters and numbers is recommended.";
  448 + case "savepass":
  449 + return "Login using your new password." .
  450 + "<small><br />This page automatically open it within 10 seconds</small>";
  451 + case "accessdenied":
  452 + return "<span class=attention>Access denied.</span><br />This procedure not allowed with your privileges.";
  453 + case "problem":
  454 + return "A problem has occurred.";
  455 + case "logout":
  456 + return "You have been successfully logged out. Click <a class=attention id=reload href=\"../\">here</a> if you wish to log in again." .
  457 + "<small><br />This page automatically open it within <span id=counter>10</span> seconds</small>";
  458 + default:
  459 + return "";
  460 + }
  461 +}
  462 +
  463 +/*
  464 + *
  465 + * name: getorphan
  466 + * @param no
  467 + * @return an array with found filenames
  468 + *
  469 + * Find and check local files for importing
  470 + *
  471 + */
  472 +function getorphan() {
  473 + global $conf;
  474 + global $user;
  475 +
  476 + $files = ' ' . implode(' ', scandir($conf->Path)) . ' ';
  477 + $mzones = $user->getMasters();
  478 + $szones = $user->getSlaves();
  479 + foreach ($mzones as $id) {
  480 + $z = new masterZone(intval($id));
  481 + $z->loadZoneHead();
  482 + $zone = $z->getZoneHeadRaw();
  483 + $files = str_replace(' ' . $zone['name'] . ' ', ' ', $files);
  484 + }
  485 + foreach ($szones as $id) {
  486 + $z = new slaveZone(intval($id));
  487 + $z->loadZoneHead();
  488 + $zone = $z->getZoneHeadRaw();
  489 + $files = str_replace(' ' . $zone['name'] . ' ', ' ', $files);
  490 + }
  491 + $vzf = array();
  492 + foreach (explode(' ', trim($files)) as $entry) {
  493 + if ((is_file($conf->Path . $entry)) && (preg_replace('/\.(signed|private|key|krf|jnl|bind)$/', '', $entry) == $entry)) {
  494 + if (checkZoneFile($conf->Path . $entry, $entry)) {
  495 + $vzf[] = hostToIdn($entry);
  496 + }
  497 + }
  498 + }
  499 +
  500 + return $vzf;
  501 +}
  502 +
  503 +/*
  504 + *
  505 + * name: checkZoneFile
  506 + * @param
  507 + * $file -> path the file
  508 + * $zone -> zonename
  509 + *
  510 + * @return true/false (aftert chacking the zoneile)
  511 + *
  512 + */
  513 +function checkZoneFile($file, $zone) {
  514 + global $conf;
  515 +
  516 + $cmd = $conf->namedCheckZone . " -i local " . $zone. " " . $file . " 2>/dev/stdout";
  517 + unset($coutput);
  518 + exec($cmd, $coutput, $exit);
  519 + return ($coutput[sizeof($coutput)-1] == 'OK');
  520 +}
  521 +
  522 +/*
  523 + *
  524 + * name: menu_buttons
  525 + * @param no
  526 + * @return no
  527 + *
  528 + * Generates the menu entries
  529 + *
  530 + */
  531 +function menu_buttons() {
  532 + global $user;
  533 + global $smarty;
  534 + global $src;
  535 + global $base;
  536 +
  537 + $cmasters = $user->getCommitableZones('master');
  538 + $cmc = (is_array($cmasters)) ? sizeof($cmasters) : 0;
  539 + $cslaves = intval($user->getCommitableZones('slave'));
  540 + $csc = (is_array($cslaves)) ? sizeof($cslaves) : 0;
  541 + $commitables = $cmc + $csc;
  542 + if($commitables == 0) {
  543 + $committext = "";
  544 + $smarty->assign("donotcommit","yes");
  545 + }
  546 + else {
  547 + $committext = "\" id=\"commitable\" class=\"attention";
  548 + }
  549 +
  550 + if (sizeof($user->getUnvalidatedZones('master')) +
  551 + sizeof($user->getUnvalidatedZones('slave')) +
  552 + sizeof($user->getDeletedZones('slave')) +
  553 + sizeof($user->getDeletedZones('master')) > 0) {
  554 + $maintext = "\" class=\"attention";
  555 + }
  556 + else {
  557 + $maintext = "";
  558 + }
  559 +
  560 + return array(
  561 + array("title" => "Main", "link" => $base . $maintext),
  562 + array("title" => "Master zones", "link" => $src . "zonelist.php"),
  563 + array("title" => "Slave zones", "link" => $src . "slave_zonelist.php"),
  564 + array("title" => "Import zones", "link" => $src . "upload.php"),
  565 + array("title" => "Users", "link" => $src . "userlist.php"),
  566 + array("title" => "Change password", "link" => $src . "chpass.php"),
  567 + array("title" => "Commit changes", "link" => $src . "commit.php" . $committext),
  568 + array("title" => "Options", "link" => $src . "options.php"),
  569 + array("title" => "Log out", "link" => $src . "logout.php")
  570 + );
  571 +}
  572 +
  573 +?>
... ...
src/logout.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * logout.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Call the logout
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +logout();
  31 +
  32 +?>
... ...
src/newuser.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * newuser.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Provides info for the user creation page.
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +if($user->isAdmin()) {
  31 + $smarty->assign("pagetitle", "New user");
  32 + $smarty->assign("admin_array", array("yes", "no"));
  33 + $smarty->assign("template", "newuser.tpl");
  34 + $smarty->assign("help", help("newuser"));
  35 + $smarty->assign("menu_button", menu_buttons());
  36 + $smarty->display("main.tpl");
  37 +}
  38 +else {
  39 + access_denied();
  40 +}
  41 +
  42 +?>
... ...
src/newzone.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * newzone.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Gathering data for the new master zone form
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +if($user->isAdmin()) {
  31 + $smarty->assign("pagetitle", "New master zone");
  32 + $smarty->assign("userlist", $user->getAllusers());
  33 + $smarty->assign("current_user", $user->getId());
  34 + $smarty->assign("pri_dns", $conf->pri_dns);
  35 + $smarty->assign("sec_dns", $conf->sec_dns);
  36 + $smarty->assign("template", "newzone.tpl");
  37 + $smarty->assign("help", help("newzone"));
  38 + $smarty->assign("menu_button", menu_buttons());
  39 + $smarty->display("main.tpl");
  40 +}
  41 +else {
  42 + access_denied();
  43 +}
  44 +?>
... ...
src/options.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * options.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Options entry page
  25 + *
  26 + */
  27 +
  28 +if($_SERVER['REQUEST_METHOD'] == 'POST') {
  29 + include("optionswrite.php");
  30 +}
  31 +include("optionsread.php");
  32 +
  33 +?>
... ...
src/optionsread.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * optionsread.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Reads and provides informations for the options page
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +if($user->isAdmin()) {
  31 + $res = $db->query("SELECT prefkey, prefval FROM options " .
  32 + "WHERE preftype = 'record' ORDER by prefkey"
  33 + );
  34 + if (MDB2::isError($res)) {
  35 + $smarty->assign("popuperror", $res->getMessage() . "<br />" . $res->getDebugInfo());
  36 + problem();
  37 + }
  38 + $recordarray = array();
  39 + $rows = $res->numRows();
  40 + for($x=0, $y=0, $i=0; $i<$rows; $y++, $i++) {
  41 + if($y == 4) {
  42 + $x++;
  43 + $y = 0;
  44 + }
  45 + $recordarray[$x][$y] = $res->fetchRow();
  46 + }
  47 + $options = array();
  48 + $res = $db->query("SELECT prefkey, prefval FROM options " .
  49 + "WHERE preftype = 'normal' ORDER by prefkey"
  50 + );
  51 + if (MDB2::isError($res)) {
  52 + $smarty->assign("popuperror", $res->getMessage() . "<br />" . $res->getDebugInfo());
  53 + problem();
  54 + }
  55 + while ($rec = $res->fetchRow()) {
  56 + switch ($rec['prefkey']) {
  57 + case 'hostmaster':
  58 + $key = 0;
  59 + break;
  60 + case 'prins':
  61 + $key = 1;
  62 + $rec['prefval'] = idnToHost($rec['prefval']);
  63 + break;
  64 + case 'secns':
  65 + $key = 2;
  66 + $rec['prefval'] = idnToHost($rec['prefval']);
  67 + break;
  68 + case 'master':
  69 + $key = 3;
  70 + $rec['prefval'] = idnToHost($rec['prefval']);
  71 + break;
  72 + default:
  73 + $key = 4;
  74 + }
  75 + $options[$key] = $rec;
  76 + }
  77 + $smarty->assign("records", $recordarray);
  78 + $smarty->assign("options", $options);
  79 + $smarty->assign("pagetitle", "Options");
  80 + $smarty->assign("template", "optionsread.tpl");
  81 + $smarty->assign("help", help("optionsread"));
  82 + $smarty->assign("menu_button", menu_buttons());
  83 + $smarty->display("main.tpl");
  84 +} else {
  85 + access_denied();
  86 +}
  87 +
  88 +?>
... ...
src/optionswrite.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * optionswrite.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + **********************************************************************
  23 + *
  24 + * Process the options form and save the changes
  25 + *
  26 + */
  27 +
  28 +require_once "include.php";
  29 +
  30 +if($user->isAdmin()) {
  31 + $allrec = array();
  32 + foreach($_POST as $key => $value) {
  33 + $val = $value;
  34 + switch ($key) {
  35 + case 'master':
  36 + case 'prins':
  37 + case 'secns':
  38 + $val = hostToIdn(preg_replace('/([\s\r\n]+|\.$)/', '', $value));
  39 + break;
  40 + case 'range':
  41 + $val = (intval($value) > 0) ? intval($value) : 10;
  42 + break;
  43 + case 'hostmaster':
  44 + $val = preg_replace('/([\s\r\n]+|\.$)/', '', $value);
  45 + break;
  46 + default:
  47 + $val = ((strtolower($value) == 'on') || (strtolower($value) == 'off')) ? strtolower($value) : 'off';
  48 + }
  49 + $allrec[$key] = $val;
  50 + }
  51 + foreach($allrec as $key => $value) {
  52 + $res = $db->query("UPDATE options SET prefval = '" . $value . "' " .
  53 + "WHERE prefkey = '" . $key . "'"
  54 + );
  55 + }
  56 +}
  57 +else {
  58 + access_denied();
  59 +}
  60 +
  61 +?>
... ...
src/record.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($_SERVER['REQUEST_METHOD'] == 'POST') {
  5 + include("recordwrite.php");
  6 +}
  7 +include("recordread.php");
  8 +
  9 +?>
... ...
src/recordread.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$znum = (intval($_GET['i']) > 0) ? intval($_GET['i']) : NULL;
  5 +
  6 +if ($znum) {
  7 + if ($user->isOwned($znum, 'master', 'live')) {
  8 + $zone = new masterZone(array('id' => $znum));
  9 + $zone->loadZone();
  10 + $zonerec = $zone->getZoneHead();
  11 + $currpage = ((isset($_GET['page'])) && (intval($_GET['page']) > 0)) ? $currpage = intval($_GET['page']) : 1;
  12 + $allrec = $zone->getRecords(true);
  13 + $count = sizeof($allrec);
  14 + $fromto = makePart($count, $currpage);
  15 + $rec = array();
  16 +
  17 + for ($i=$fromto[0];$i<$fromto[1];$i++) {
  18 + $allrec[$i]['ttl'] = ($allrec[$i]['ttl'] > 0) ? $allrec[$i]['ttl'] : '';
  19 + $rec[] = $allrec[$i];
  20 + }
  21 +
  22 + $users = $user->getAllusers();
  23 + $types = $conf->parameters;
  24 + $err = '';
  25 + $err .= ((!is_array($zonerec)) || (!is_array($rec))) ? $zone->getErr() : '';
  26 + $err .= (!is_array($users)) ? $user->getErr() : '';
  27 + $err .= (!is_array($types)) ? "Record types not foud\n" : '';
  28 + if ($err > '') {
  29 + $smarty->assign("popuperror",implode("<br />", explode("\n", $err)));
  30 + }
  31 + $smarty->assign("zone", $zonerec);
  32 + $smarty->assign("pagetitle", "Editing master zone");
  33 + $smarty->assign("rcount", sizeof($rec));
  34 + $smarty->assign("record",$rec);
  35 + $smarty->assign("types", $types);
  36 + $smarty->assign("userlist", $users);
  37 + $smarty->assign("template", "recordread.tpl");
  38 + $smarty->assign("help", help("recordread"));
  39 + $smarty->assign("menu_button", menu_buttons());
  40 + $smarty->assign("page_root", $src . "record.php?i=" . $_GET['i'] . "&amp;");
  41 + $smarty->display("main.tpl");
  42 + } else {
  43 + problem("notown");
  44 + }
  45 +} else {
  46 + access_denied();
  47 +}
  48 +
  49 +?>
... ...
src/recordwrite.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$znum = (intval($_GET['i']) > 0) ? intval($_GET['i']) : NULL;
  5 +
  6 +if ($znum) {
  7 + if ($user->isOwned($znum, 'master', 'live')) {
  8 + $zone = new masterZone(array('id' => $znum));
  9 + $zone->loadZone();
  10 + $zonerec = $zone->getZoneHead();
  11 + $zrec = array();
  12 + foreach (array('refresh', 'expire', 'retry', 'ttl', 'secured', 'pri_dns', 'sec_dns', 'owner') as $key) {
  13 + $zrec[$key] = ((isset($_POST[$key])) and ($_POST[$key] > '')) ? $_POST[$key] : $zonerec[$key];
  14 + }
  15 + $zrec['valid'] = 'may';
  16 + $zone->setZoneHead($zrec);
  17 + $zone->saveZoneHead();
  18 + $total = ((isset($_POST['total'])) && ($_POST['total'] > 0)) ? $_POST['total'] : 0;
  19 + for ($x = 0; $x < $total; $x++) {
  20 + if (isset($_POST['delete'][$x])) {
  21 + $zone->eraseRecord(intval($_POST['host_id'][$x]));
  22 + } else {
  23 + $nrec=array();
  24 + foreach (array('host', 'ttl', 'type', 'pri', 'destination') as $key) {
  25 + $pkey = ($key == 'ttl') ? 'rttl' : $key;
  26 + $nrec[$key] = (isset($_POST[$pkey][$x])) ? $_POST[$pkey][$x] : '';
  27 + $nrec[$key] = (($key == 'ttl') && ($nrec[$key] == '')) ? 0 :$nrec[$key];
  28 + $nrec[$key] = (($key == 'pri') && ($nrec[$key] == '')) ? 10 :$nrec[$key];
  29 + $nrec[$key] = (($key == 'host') && ($nrec[$key] == '')) ? '@' :$nrec[$key];
  30 + $nrec[$key] = (($key == 'destination') && ($nrec[$key] == '')) ? '@' :$nrec[$key];
  31 + }
  32 + if ($nrec['host'] != $nrec['destination']) {
  33 + $urec = new masterRecord(intval($_POST['host_id'][$x]));
  34 + $urec->loadRecord();
  35 + $urec->setRecord($nrec);
  36 + $xrec = $urec->getRecordRaw();
  37 + $urec->saveRecord();
  38 + }
  39 + }
  40 + }
  41 + $zone->clearZone();
  42 + $zone->loadZone();
  43 + $nrec = array();
  44 + foreach (array('host', 'ttl', 'type', 'pri', 'destination') as $key) {
  45 + $nrec[$key] = ((isset($_POST['new' . $key])) && ($_POST['new' . $key] > '')) ? $_POST['new' . $key] : NULL;
  46 + }
  47 + if ($nrec['host'] != $nrec['destination']) {
  48 + $nrec['pri'] = ($nrec['type'] == 'MX') ? 10 : 0;
  49 + $nrec['ttl'] = intval($nrec['ttl']);
  50 + $nrec['zone'] = $znum;
  51 + $zone->addRecord($nrec);
  52 + }
  53 + $zone->saveZone();
  54 + } else {
  55 + problem("notown");
  56 + }
  57 +} else {
  58 + access_denied();
  59 +}
  60 +
  61 +?>
... ...
src/savepass.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if ($user->getPasswordHash() == $_POST['password_old']) {
  5 + if ((strlen($_POST['password_one']) == 32) && ($session->isEnoughOld())) {
  6 + $user->set(NULL, $_POST['password_one']);
  7 + $_SESSION['p'] = $user->getPasswordHash();
  8 + $smarty->assign("pagetitle", "Change password");
  9 + $smarty->assign("template", "savepass.tpl");
  10 + $smarty->assign("help", help("savepass"));
  11 + $smarty->assign("menu_button", menu_buttons());
  12 + $smarty->display("main.tpl");
  13 + } else {
  14 + problem();
  15 + }
  16 +} else {
  17 + problem("unauth");
  18 +}
  19 +
  20 +?>
... ...
src/slave_deletezone.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$zoneid = intval($_GET['i']);
  5 +
  6 +if ($zoneid > 0) {
  7 + if ($user->isOwned($zoneid, 'slave')) {
  8 + $smarty->assign("pagetitle", "Delete slave zone");
  9 + $zone = new slaveZone($zoneid);
  10 + $zone->loadZoneHead();
  11 + $res = $zone->getZoneHead();
  12 + $smarty->assign("zone", $res['name']);
  13 + $smarty->assign("zoneid", $zoneid);
  14 + $smarty->assign("template", "slave_deletezone.tpl");
  15 + $smarty->assign("help", help("deletezone"));
  16 + $smarty->assign("menu_button", menu_buttons());
  17 + $smarty->display("main.tpl");
  18 + } else {
  19 + problem('notown');
  20 + }
  21 +} else {
  22 + problem();
  23 +}
  24 +
  25 +?>
... ...
src/slave_newzone.php 0 → 100644
  1 +<?php
  2 +/*
  3 + * slave_newzone.php
  4 + *
  5 + * Copyright 2015 Péter Szládovics <peti@szladovics.hu>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  20 + * MA 02110-1301, USA.
  21 + *
  22 + * Gathers data from config and the db to present informations to the
  23 + * template.
  24 + *
  25 + */
  26 +
  27 +require_once "include.php";
  28 +
  29 +if($user->isAdmin()) {
  30 + $smarty->assign("pagetitle", "New slave zone");
  31 + $smarty->assign("userlist", $user->getAllusers());
  32 + $smarty->assign("current_user", $user->getId());
  33 + $smarty->assign("master", $conf->master);
  34 + $smarty->assign("template", "slave_newzone.tpl");
  35 + $smarty->assign("help", help("newslavezone"));
  36 + $smarty->assign("menu_button", menu_buttons());
  37 + $smarty->display("main.tpl");
  38 +}
  39 +else {
  40 + access_denied();
  41 +}
  42 +
  43 +?>
... ...
src/slave_record.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$i = intval($_GET['i']);
  5 +
  6 +if ($i > 0) {
  7 + if ($user->isOwned($i, 'slave', 'live')) {
  8 + $sz = new slaveZone($i);
  9 + $sz->loadZoneHead();
  10 + $zone = $sz->getZoneHead();
  11 + $smarty->assign("zone", $zone);
  12 + $smarty->assign("pagetitle", "Editing slave zone");
  13 + $smarty->assign("userlist", $user->getAllusers());
  14 + $smarty->assign("template", "slave_recordread.tpl");
  15 + $smarty->assign("help", help("recordread"));
  16 + $smarty->assign("menu_button", menu_buttons());
  17 + $smarty->assign("page_root", $src . "slave_record.php?i=" . $_GET['i'] . "&amp;");
  18 + $smarty->display("main.tpl");
  19 + } else {
  20 + problem('notown');
  21 + }
  22 +} else {
  23 + problem();
  24 +}
  25 +
  26 +?>
... ...
src/slave_zoneadd.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($user->isAdmin()) {
  5 + $arr = array();
  6 + foreach (array('name', 'master', 'owner') as $key) {
  7 + $arr[$key] = $_POST[$key];
  8 + }
  9 + $nz = new slaveZone($arr);
  10 + if (!$nz->loadZoneHead()) {
  11 + $nz->setZoneHead($arr);
  12 + $nz->saveZoneHead();
  13 + $user->loadUserZones();
  14 + } else {
  15 + problem("existzone");
  16 + }
  17 +} else {
  18 + access_denied();
  19 +}
  20 +
  21 +?>
... ...
src/slave_zonedelete.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$zoneid = intval($_GET['i']);
  5 +
  6 +if($user->isOwned($zoneid, 'slave')) {
  7 + if($zoneid > 0) {
  8 + $zone = new slaveZone($zoneid);
  9 + $zone->loadZoneHead();
  10 + $zone->setZoneHead(array('updated' => 'del'));
  11 + $zone->saveZoneHead();
  12 + }
  13 + else {
  14 + problem();
  15 + }
  16 +}
  17 +else {
  18 + problem("notown");
  19 +}
  20 +
  21 +?>
... ...
src/slave_zonelist.php 0 → 100644
  1 +<?php
  2 +if($_SERVER['REQUEST_METHOD'] == 'POST') {
  3 + if($_POST['Submit'] == 'Add zone') {
  4 + include("slave_zoneadd.php");
  5 + }
  6 + if($_POST['Submit'] == 'Save') {
  7 + include("slave_zonewrite.php");
  8 + }
  9 +}
  10 +if(isset($_GET['delete']) && $_GET['delete'] == 'y') {
  11 + include("slave_zonedelete.php");
  12 +}
  13 +
  14 +include("slave_zoneread.php");
  15 +
  16 +?>
... ...
src/slave_zoneread.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$zones = $user->getSlaves('live');
  5 +$count = sizeof($zones);
  6 +$maxitems = intval($conf->range);
  7 +$currpage = ((isset($_GET['page'])) && (intval($_GET['page']) > 0)) ? $currpage = intval($_GET['page']) : 1;
  8 +$fromto = makePart($count, $currpage);
  9 +$buffer = array();
  10 +
  11 +$i = (isset($_GET['i'])) ? intval($_GET['i']) : NULL;
  12 +
  13 +if ((isset($i)) && (isset($_GET['check'])) && ($_GET['check'] = 'y') ) {
  14 + if ($i > 0) {
  15 + if ($user->isOwned($i, 'slave', 'live')) {
  16 + $sz = new slaveZone($i);
  17 + if ($sz->validateZone($conf->dig)) {
  18 + $arr = $sz->getZoneHead($i);
  19 + $arr['updated'] = 'yes';
  20 + $arr['valid'] = 'yes';
  21 + $sz->setZoneHead($arr);
  22 + $sz->saveZoneHead();
  23 + } else {
  24 + $smarty->assign("popuperror", $sz->getErr());
  25 + }
  26 + } else {
  27 + problem('notown');
  28 + }
  29 + } else {
  30 + problem();
  31 + }
  32 +}
  33 +
  34 +for ($i=$fromto[0];$i<$fromto[1];$i++) {
  35 + $zone = new slaveZone(array('id' => $zones[$i]));
  36 + $zone->loadZoneHead();
  37 + $buffer[] = $zone->getZoneHead();
  38 + unset($zone);
  39 +}
  40 +
  41 +$smarty->assign("zonelist", $buffer);
  42 +$smarty->assign("pagetitle", "Slave zones");
  43 +$smarty->assign("template", "slave_zoneread.tpl");
  44 +$smarty->assign("help", help("zoneread"));
  45 +$smarty->assign("menu_button", menu_buttons());
  46 +$smarty->assign("page_root", $src . "zonelist.php?");
  47 +$smarty->display("main.tpl");
  48 +
  49 +?>
... ...
src/slave_zoneview.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$param = intval($_GET['i']);
  5 +
  6 +if ($param > 0) {
  7 + if ($user->isOwned($param, 'slave')) {
  8 + $smarty->assign("pagetitle", "Dump slave zone");
  9 + $zone = new slaveZone(array('id' => $_GET['i']));
  10 + $zone->loadZoneHead();
  11 + $zonedef = '';
  12 + $head = $zone->getZoneHead();
  13 + $headraw = $zone->getZoneHeadRaw();
  14 + $name = $head['name'];
  15 + $zonetype = "slave zone ";
  16 + $ownerid = $head['owner'];
  17 + $ouser = new User(array('id' => $ownerid));
  18 + $owner = $ouser->getFullName();
  19 + if ((isset($_GET['pre'])) && ($_GET['pre'] == 'y')) {
  20 + $zonedef = $zone->dumpZone($conf->dig);
  21 + $zonetype .= "(AXFR dump from it's master)";
  22 + } else {
  23 + $zonetype .= "(locally mirrored)";
  24 + $lines = file($conf->path . $headraw['name']);
  25 + $zonedef = '';
  26 + foreach ($lines as $line) {
  27 + $zonedef .= $line;
  28 + }
  29 + }
  30 + $smarty->assign("zonename", $name);
  31 + $smarty->assign("zonetype", $zonetype);
  32 + $smarty->assign("owner", $owner);
  33 + $smarty->assign("zonedef", $zonedef);
  34 + $smarty->assign("template", "zoneview.tpl");
  35 + $smarty->assign("help", help("zoneview"));
  36 + $smarty->assign("menu_button", menu_buttons());
  37 + $smarty->display("main.tpl");
  38 + } else {
  39 + problem('notown');
  40 + }
  41 +} else {
  42 + problem();
  43 +}
  44 +
  45 +?>
... ...
src/slave_zonewrite.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$i = intval($_GET['i']);
  5 +$name = (isset($_POST['name']) && (trim($_POST['name']) > '')) ? trim($_POST['name']) : '';
  6 +$owner = intval($_POST['owner']);
  7 +$master = (isset($_POST['master']) && (trim($_POST['master']) > '')) ? trim($_POST['master']) : '';
  8 +
  9 +if ((($i * $owner) > 0) && ($name > '') && ($master > '')) {
  10 + if ($user->isOwned($i, 'master', 'live')) {
  11 + $sz = new slaveZone(array(
  12 + 'id' => $i,
  13 + 'name' => $name,
  14 + 'master' => $master,
  15 + 'owner' => $owner,
  16 + 'updated' => 'yes',
  17 + 'valid' => 'may',
  18 + ));
  19 + $sz->saveZoneHead();
  20 + } else {
  21 + problem('notown');
  22 + }
  23 +} else {
  24 + problem();
  25 +}
  26 +?>
... ...
src/upload.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($user->isAdmin()) {
  5 + $files = getorphan();
  6 + $smarty->assign("pagetitle", "Import master zones");
  7 + $smarty->assign("count",sizeof($files));
  8 + $smarty->assign("files",$files);
  9 + $smarty->assign("template", "upload.tpl");
  10 + $smarty->assign("help", help("upload"));
  11 + $smarty->assign("menu_button", menu_buttons());
  12 + $smarty->display("main.tpl");
  13 +}
  14 +else {
  15 + access_denied();
  16 +}
  17 +?>
... ...
src/user.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($_SERVER['REQUEST_METHOD'] == 'POST') {
  5 + include("userwrite.php");
  6 +} else {
  7 + $smarty->assign("success",'');
  8 +}
  9 +include("userread.php");
  10 +
  11 +?>
... ...
src/useradd.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if ($user->isAdmin()) {
  5 + if ((strlen($_POST['password_']) == 32) &&
  6 + (isset($_POST['username_'])) &&
  7 + (strlen($_POST['username_']) > 2)) {
  8 + $real = ((isset($_POST['realname'])) && ($_POST['realname'] >= '')) ? $_POST['realname'] : $_POST['username_'];
  9 + $urec = array(
  10 + 'id' => 0,
  11 + 'username' => $_POST['username_'],
  12 + 'realname' => $real,
  13 + 'admin' => $_POST['admin'],
  14 + 'password' => $_POST['password_'],
  15 + );
  16 + $nuser = new User($urec);
  17 + if ($nuser->getId() == 0) {
  18 + problem();
  19 + }
  20 + } else {
  21 + problem();
  22 + }
  23 +} else {
  24 + access_denied();
  25 +}
  26 +
  27 +?>
... ...
src/userdelete.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($user->isAdmin()) {
  5 + $i = intval($_GET['i']);
  6 + if (($i > 1) && ($session->isEnoughOld())) {
  7 + $us = new User($i);
  8 + $us->eraseUser();
  9 + } else {
  10 + problem();
  11 + }
  12 +} else {
  13 + access_denied();
  14 +}
  15 +?>
... ...
src/userlist.php 0 → 100644
  1 +<?php
  2 +if($_SERVER['REQUEST_METHOD'] == 'POST') {
  3 + include("useradd.php");
  4 +}
  5 +if(isset($_GET['delete']) && $_GET['delete'] == 'y') {
  6 + include("userdelete.php");
  7 +}
  8 +
  9 +include("userlistread.php");
  10 +
  11 +?>
... ...
src/userlistread.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($user->isAdmin()) {
  5 + $smarty->assign("pagetitle", "Users");
  6 + $usermap = $user->getAllusers();
  7 + $currpage = ((isset($_GET['page'])) && (intval($_GET['page']) > 0)) ? $currpage = intval($_GET['page']) : 1;
  8 + $count = sizeof($usermap);
  9 + $fromto = makePart($count, $currpage);
  10 + $listed = array();
  11 + for ($i=$fromto[0];$i<$fromto[1];$i++) {
  12 + $listed[] = $usermap[$i];
  13 + }
  14 + $smarty->assign("userlist", $listed);
  15 + $smarty->assign("template", "userlistread.tpl");
  16 + $smarty->assign("help", help("userlistread"));
  17 + $smarty->assign("menu_button", menu_buttons());
  18 + $smarty->assign("page_root", $src . "userlist.php?");
  19 + $smarty->display("main.tpl");
  20 +}
  21 +else {
  22 + access_denied();
  23 +}
  24 +
  25 +?>
... ...
src/userread.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($user->isAdmin()) {
  5 + $i = (isset($_GET['i'])) ? intval($_GET['i']) : 0;
  6 + if ($i > 1) {
  7 + $smarty->assign("pagetitle", "Viewing user");
  8 + $smarty->assign("admin_array", array("yes", "no"));
  9 + $xuser = new User($i);
  10 + $data = $xuser->getUser();
  11 + $smarty->assign("user", $data);
  12 + $xuser->loadUserZones();
  13 + $masters = $xuser->getMasters('live');
  14 + $masterlist = array();
  15 + foreach ($masters as $id) {
  16 + $temp = new masterZone(intval($id));
  17 + $temp->loadZoneHead();
  18 + $head = $temp->getZoneHead();
  19 + $temp = array();
  20 + foreach (array('id', 'name', 'serial') as $key) {
  21 + $temp[$key] = $head[$key];
  22 + }
  23 + $masterlist[] = $temp;
  24 + }
  25 + $slaves = $xuser->getSlaves('live');
  26 + $slavelist = array();
  27 + foreach ($slaves as $id) {
  28 + $temp = new slaveZone(intval($id));
  29 + $temp->loadZoneHead();
  30 + $head = $temp->getZoneHead();
  31 + $temp = array();
  32 + foreach (array('id', 'name', 'master') as $key) {
  33 + $temp[$key] = $head[$key];
  34 + }
  35 + $slavelist[] = $temp;
  36 + $temp = array();
  37 + }
  38 + $smarty->assign("zonelist", $masterlist);
  39 + $smarty->assign("szonelist", $slavelist);
  40 + $smarty->assign("template", "userread.tpl");
  41 + $smarty->assign("help", help("userread"));
  42 + $smarty->assign("menu_button", menu_buttons());
  43 + $smarty->display("main.tpl");
  44 + } else {
  45 + problem();
  46 + }
  47 +} else {
  48 + access_denied();
  49 +}
  50 +
  51 +?>
... ...
src/userwrite.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($user->isAdmin()) {
  5 + $adm = (isset($_POST['admin'])) ? $_POST['admin'] : '';
  6 + $pass = (isset($_POST['password'])) ? $_POST['password'] : '';
  7 + $rnam = (isset($_POST['realname'])) ? $_POST['realname'] : '';
  8 + $i = (isset($_GET['i'])) ? intval($_GET['i']) : 0;
  9 + if (($i > 1) && ($session->isEnoughOld())) {
  10 + $smarty->assign("pagetitle", "Viewing user");
  11 + $newu = new User($i);
  12 + $newu->set($rnam, $pass, $adm);
  13 + if ($i == $user->getId() && (
  14 + ($newu->isAdmin() xor $user->isAdmin()) ||
  15 + ($newu->getPasswordHash() <> $user->getPasswordHash())
  16 + )) {
  17 + logout();
  18 + die();
  19 + }
  20 + $smarty->assign("success","The user properties has been modified");
  21 + } else {
  22 + problem();
  23 + }
  24 +} else {
  25 + access_denied();
  26 +}
  27 +
  28 +?>
... ...
src/zoneadd.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +if($user->isAdmin()) {
  5 + $arr = array(
  6 + 'name' => $_POST['name'],
  7 + 'pri_dns' => $_POST['pri_dns'],
  8 + 'sec_dns' => $_POST['sec_dns'],
  9 + 'refresh' => $_POST['refresh'],
  10 + 'retry' => $_POST['retry'],
  11 + 'expire' => $_POST['expire'],
  12 + 'ttl' => $_POST['ttl'],
  13 + 'owner' => $_POST['owner'],
  14 + );
  15 + $nz = new masterZone($arr);
  16 + if (!$nz->loadZoneHead()) {
  17 + $nz->setZoneHead($arr);
  18 + $nz->saveZoneHead();
  19 + $www = ((isset($_POST['www'])) && ($_POST['www'] >'')) ? $_POST['www'] : NULL;
  20 + if ($www){
  21 + $type = (filter_var($www, FILTER_VALIDATE_IP)) ? 'A' : 'CNAME';
  22 + if ($type == 'A') {
  23 + $nz->addRecord(array(
  24 + 'host' => '@',
  25 + 'type' => 'A',
  26 + 'destination' => $www,
  27 + ));
  28 + $nz->addRecord(array(
  29 + 'host' => 'www',
  30 + 'type' => 'CNAME',
  31 + 'destination' => '@',
  32 + ));
  33 + } else {
  34 + $nz->addRecord(array(
  35 + 'host' => 'www',
  36 + 'type' => 'CNAME',
  37 + 'destination' => $www,
  38 + ));
  39 + }
  40 + }
  41 + $ftp = ((isset($_POST['ftp'])) && ($_POST['ftp'] >'')) ? $_POST['ftp'] : NULL;
  42 + if ($ftp) {
  43 + $type = (filter_var($ftp, FILTER_VALIDATE_IP)) ? 'A' : 'CNAME';
  44 + $nz->addRecord(array(
  45 + 'host' => 'ftp',
  46 + 'type' => $type,
  47 + 'destination' => $ftp,
  48 + ));
  49 + }
  50 + $mail = ((isset($_POST['mail'])) && ($_POST['mail'] >'')) ? $_POST['mail'] : NULL;
  51 + if ($mail) {
  52 + $type = (filter_var($mail, FILTER_VALIDATE_IP)) ? 'A' : 'MX';
  53 + $destination = ($type == 'A') ? 'mail' : $mail;
  54 + if ($type == 'A') {
  55 + $nz->addRecord(array(
  56 + 'host' => 'mail',
  57 + 'type' => $type,
  58 + 'destination' => $mail,
  59 + ));
  60 + $type = 'MX';
  61 + }
  62 + $nz->addRecord(array(
  63 + 'host' => '@',
  64 + 'type' => $type,
  65 + 'destination' => $destination,
  66 + 'pri' => 10,
  67 + ));
  68 + }
  69 + $nz->saveZone();
  70 + $user->loadUserZones();
  71 + } else {
  72 + problem("existzone");
  73 + }
  74 +}
  75 +
  76 +?>
... ...
src/zonecheck.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$param = (isset($_GET['i'])) ? intval($_GET['i']) : 0;
  5 +
  6 +if($user->isOwned($param, 'master')) {
  7 + $zone = new masterZone(array('id' => $_GET['i']));
  8 + $file = tempnam($conf->Tmp_Path,"zone_");
  9 + $check = $zone->validateZone($file, $conf->HostMaster, $conf->NamedCheckZone);
  10 + if (!$check[0]) {
  11 + $smarty->assign("popuperror",$check[1]);
  12 + }
  13 + if (file_exists($file)) {
  14 + unlink($file);
  15 + }
  16 +} else {
  17 + problem('notown');
  18 +}
  19 +
  20 +?>
... ...
src/zonedelete.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$zoneid = intval($_GET['i']);
  5 +
  6 +if($user->isOwned($zoneid, 'master')) {
  7 + if($zoneid > 0) {
  8 + $zone = new masterZone($zoneid);
  9 + $zone->loadZoneHead();
  10 + $zone->setZoneHead(array('updated' => 'del'));
  11 + $zone->saveZoneHead();
  12 + }
  13 + else {
  14 + problem();
  15 + }
  16 +}
  17 +else {
  18 + problem("notown");
  19 +}
  20 +
  21 +?>
... ...
src/zonelist.php 0 → 100644
  1 +<?php
  2 +if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  3 + include("zoneadd.php");
  4 +}
  5 +if ((isset($_GET['delete'])) &&
  6 + ($_GET['delete'] == 'y') &&
  7 + (isset($_GET['i'])) &&
  8 + (is_numeric($_GET['i']))) {
  9 + include("zonedelete.php");
  10 +}
  11 +if ((isset($_GET['check'])) &&
  12 + ($_GET['check'] == 'y') &&
  13 + (isset($_GET['i'])) &&
  14 + (is_numeric($_GET['i']))) {
  15 + include "zonecheck.php";
  16 +}
  17 +
  18 +include("zoneread.php");
  19 +
  20 +?>
... ...
src/zonepview.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$param = (isset($_GET['i'])) ? intval($_GET['i']) : 0;
  5 +
  6 +if ($param > 0) {
  7 + if($user->isOwned($param, 'master')) {
  8 + $smarty->assign("pagetitle", "Preview master zone");
  9 + $zone = new masterZone(array('id' => $_GET['i']));
  10 + $fname = tempnam($conf->Tmp_Path,"zone_");
  11 + $zone->writeZone($fname, $conf->HostMaster);
  12 + $head = $zone->getZoneHead();
  13 + $name = $head['name'];
  14 + $issec = ($head['secured'] == "yes");
  15 + $sec = (($_GET['s'] == "1") && ($issec));
  16 + $zonetype = "master zone";
  17 + $zonetype .= (!$issec) ? " not" : "";
  18 + $zonetype .= " secured, displayed as plain";
  19 + $ownerid = $head['owner'];
  20 + $ouser = new User(array('id' => $ownerid));
  21 + $owner = $ouser->getFullName();
  22 + if (file_exists($fname)) {
  23 + $lines = file($fname);
  24 + $zonedef = implode("", $lines);
  25 + unlink($fname);
  26 + } else {
  27 + $zonedef = NULL;
  28 + $smarty->assign("popuperror", "There is a problem with this zone!");
  29 + }
  30 + $smarty->assign("zonename", $name);
  31 + $smarty->assign("zonetype", $zonetype);
  32 + $smarty->assign("owner", $owner);
  33 + $smarty->assign("zonedef", $zonedef);
  34 + $smarty->assign("template", "zoneview.tpl");
  35 + $smarty->assign("help", help("zonepview"));
  36 + $smarty->assign("menu_button", menu_buttons());
  37 + $smarty->display("main.tpl");
  38 + } else {
  39 + problem('notown');
  40 + }
  41 +} else {
  42 + problem();
  43 +}
  44 +?>
... ...
src/zoneread.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$zones = $user->getMasters('live');
  5 +$count = sizeof($zones);
  6 +$maxitems = intval($conf->range);
  7 +$currpage = ((isset($_GET['page'])) && (intval($_GET['page']) > 0)) ? $currpage = intval($_GET['page']) : 1;
  8 +$fromto = makePart($count, $currpage);
  9 +$buffer = array();
  10 +
  11 +for ($i=$fromto[0];$i<$fromto[1];$i++) {
  12 + $zone = new masterZone(array('id' => $zones[$i]));
  13 + $zone->loadZoneHead();
  14 + $buffer[] = $zone->getZoneHead();
  15 + unset($zone);
  16 +}
  17 +
  18 +$smarty->assign("zonelist", $buffer);
  19 +$smarty->assign("pagetitle", "Master zones");
  20 +$smarty->assign("template", "zoneread.tpl");
  21 +$smarty->assign("help", help("zoneread"));
  22 +$smarty->assign("menu_button", menu_buttons());
  23 +$smarty->assign("page_root", $src . "zonelist.php?");
  24 +$smarty->display("main.tpl");
  25 +
  26 +?>
... ...
src/zoneview.php 0 → 100644
  1 +<?php
  2 +require_once "include.php";
  3 +
  4 +$param = (isset($_GET['i'])) ? intval($_GET['i']) : 0;
  5 +
  6 +if ($param > 0) {
  7 + if($user->isOwned($param, 'master')) {
  8 + $smarty->assign("pagetitle", "Dump master zone");
  9 + $zone = new masterZone(array('id' => $_GET['i']));
  10 + $zone->loadZoneHead();
  11 + $head = $zone->getZoneHead();
  12 + $headraw = $zone->getZoneHeadRaw();
  13 + $name = $head['name'];
  14 + $fname = $headraw['name'];
  15 + $issec = ($head['secured'] == "yes");
  16 + $sec = (($_GET['s'] == "1") && ($issec));
  17 + $zonetype = "master zone";
  18 + $zonetype .= (!$issec) ? " not" : "";
  19 + $zonetype .= " secured, displayed as ";
  20 + $zonetype .= ($sec) ? "secured" : "plain";
  21 + $fname .= ($issec) ? '.signed' : "";
  22 + $ownerid = $head['owner'];
  23 + $ouser = new User(array('id' => $ownerid));
  24 + $owner = $ouser->getFullName();
  25 + $filename = $conf->path . $fname;
  26 + if (file_exists($filename)) {
  27 + $lines = file($conf->path . $fname);
  28 + $zonedef = '';
  29 + foreach ($lines as $line) {
  30 + $zonedef .= $line;
  31 + }
  32 + } else {
  33 + $zonedef = NULL;
  34 + $smarty->assign("popuperror", "There is no saved zonefile in the system!");
  35 + }
  36 + $smarty->assign("zonename", $name);
  37 + $smarty->assign("zonetype", $zonetype);
  38 + $smarty->assign("owner", $owner);
  39 + $smarty->assign("zonedef", $zonedef);
  40 + $smarty->assign("template", "zoneview.tpl");
  41 + $smarty->assign("help", help("zoneview"));
  42 + $smarty->assign("menu_button", menu_buttons());
  43 + $smarty->display("main.tpl");
  44 + } else {
  45 + problem('notown');
  46 + }
  47 +} else {
  48 + problem();
  49 +}
  50 +?>
... ...
static/default.css 0 → 100755
  1 +body {
  2 +margin:0;
  3 +padding:0;
  4 +background-color:#e0f0ff;
  5 +background-image:url(data:image/png;base64,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);
  6 +background-repeat:no-repeat;
  7 +background-attachment:fixed;
  8 +background-position:top-left;
  9 +font-family:Verdana;
  10 +font-size:12px;
  11 +}
  12 +div.title {
  13 +position:fixed;
  14 +opacity:.7;
  15 +box-shadow:3px 3px 10px black;
  16 +border-radius:5px;
  17 +top:15;
  18 +left:170;
  19 +right:15;
  20 +background-color:#000820;
  21 +padding:10px 15px;
  22 +color:white;
  23 +text-shadow:3px 3px 8px black;
  24 +font-size:18px;
  25 +font-weight:bold;
  26 +text-align:left;
  27 +}
  28 +div.loggeduser {
  29 +position:fixed;
  30 +top:28;
  31 +right:40;
  32 +color:yellow;
  33 +text-shadow:2 2 3 black;
  34 +font-size:12px;
  35 +text-align:right;
  36 +}
  37 +.desc {
  38 +font-size:11px;
  39 +font-weight:normal;
  40 +margin:5px 0px;
  41 +}
  42 +.copy {
  43 +font-size:11px;
  44 +margin:5px 0px;
  45 +font-weight:normal;
  46 +float:right;
  47 +color:orange;
  48 +}
  49 +div.menu {
  50 +position:fixed;
  51 +opacity:.8;
  52 +border-radius:5px;
  53 +top:142;
  54 +left:10;
  55 +width:130;
  56 +background-color:white;
  57 +padding:3px 5px 30px 5px;
  58 +color:back;
  59 +text-shadow:3px 3px 8px black;
  60 +font-size:12px;
  61 +text-align:left;
  62 +border-style:inset;
  63 +border-color:#80a0ff;
  64 +line-height:200%;
  65 +}
  66 +.tag {
  67 +font-size:18px;
  68 +margin:5px 5px;
  69 +font-weight:bold;
  70 +text-align:center;
  71 +color:black;
  72 +}
  73 +.currmenu {
  74 +float:right;
  75 +color:darkgreen;
  76 +}
  77 +a, a:visited, a:active {
  78 +text-decoration:none;
  79 +color:darkblue;
  80 +}
  81 +.deleted {
  82 +color:black;
  83 +text-decoration:line-through;
  84 +}
  85 +.attention, a.attention:visited, a.attention:active {
  86 +color:red;
  87 +}
  88 +a:hover {
  89 +color:red;
  90 +text-decoration:underline;
  91 +}
  92 +div.main {
  93 +position:absolute;
  94 +top:0;
  95 +left:0;
  96 +min-height:300px;
  97 +min-width:350px;
  98 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUgAAAD4BAMAAAB8h2LBAAAAHlBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC3KG9qAAAACnRSTlMABCUgCQ0XGxMRWRrLZAAAAoFJREFUeNrt3b1q21AchvFz7sAHzgX0g5K1REPWGqS9hQiqrZOVsWCI1k6qu3VJkO62kuXUVmRoA7Lz/vHzoFXw4z1HsxxdYD68Ti8xhq4YTlVchv/pn8b01XpOXSyOG31nzM/bxLocQf2RIWOWt+3mRP1q2+4Zl+cPD0e8o0EnQxZNvTpLe/ugfaIeWdT7ETJmzaqsztF9WT5x7/bUwTlhukNlN2RdJWfopqq6Z9uh9O+ge+X0xEPWlOvkfI2hw60d1rzdGtPljukOlDF7rJLrd6ft/THnRJkOyjAoF6MrWa9PbhxBb5Jkr7w7OPFnX7k/QBY/T4icekdz3vfM/Za3O+V0yaJMupevvjjdnpCfnHA75FunnI9fy0R8yB3yykk3ID846bZI8Su5Q75x0oEEqRZIkGqBBKkWSJBqgQSpFkiQaoEEqRZIkGqBBKkWSJBqgQSpFkiQaoEEqRZIkGqBBKkWSJBqgQSpFkiQaoEEqRZIkGqBBKkWSJBqgQSplo8FSJBS2UCmFpAmlgQJUiw7yGuQIHUCCVKtHrlOQILUyQqyBglSKZAg1RqQH510PbICCVIoI8jcCHINcg5kVpcmkBXIWZCPFpANSJBK9chV9d1JB3JWZAlyJuTKALJWRzojyNYCstBHhh75zWnXITcgLweZFpvaALLZgJwFmYOcC9lufjjtzCAbA8iiBTkLMjOC/O20CzHLTSALC8hcH5mCnA/52WnnjSAzkJeETPWRIU0zC8gU5FxI7b8Qm0FGkJeDdDaQASRIrUKIFpAhyiN9p5RHdsalPLJfcuHEAwlSLpAXhfQWkM4CcmEB6bw+0nvn5JFbpnwGiEaWJCIiIpqzPzRW7lFKbYgjAAAAAElFTkSuQmCC);
  99 +background-repeat:no-repeat;
  100 +background-position:top-left;
  101 +padding:20px 35px;
  102 +color:black;
  103 +text-shadow:3px 3px 8px grey;
  104 +text-align:left;
  105 +}
  106 +div.loginform {
  107 +position:absolute;
  108 +box-shadow:3px 3px 10px black;
  109 +border-radius:5px;
  110 +top:10;
  111 +width:90%;
  112 +height:350px;
  113 +background:linear-gradient(to bottom,rgba(255,255,255,0.2)0%,rgba(255,255,255,0.5)100%);
  114 +padding:10px 15px;
  115 +color:black;
  116 +text-shadow:3px 3px 8px grey;
  117 +text-align:left;
  118 +}
  119 +div.loginend {
  120 +position:absolute;
  121 +width:100%;
  122 +bottom:20;
  123 +color:black;
  124 +text-shadow:3px 3px 8px grey;
  125 +text-align:left;
  126 +}
  127 +div.footer {
  128 +position:fixed;
  129 +bottom:0;
  130 +left:0;
  131 +right:0;
  132 +height:18px;
  133 +background-color:darkblue;
  134 +padding:5px 15px;
  135 +color:lightgrey;
  136 +text-shadow:3px 3px 8px black;
  137 +text-align:left;
  138 +}
  139 +.disabled {
  140 +color:darkgrey;
  141 +}
  142 +.submit-button {
  143 +border-stile:outset;
  144 +background-color:#6080ff;
  145 +border-color:#6080ff;
  146 +border-radius:5px;
  147 +text-shadow:2px 2px 5px white;
  148 +color:#000838;
  149 +padding:3px 10px;
  150 +font-size:14px;
  151 +font-weight:bold;
  152 +text-decoration:none;
  153 +vertical-align:middle;
  154 +min-width:100px;
  155 +}
  156 +.submit-button:hover {
  157 +border-stile:outset;
  158 +background-color:#4058df;
  159 +border-color:#4058df;
  160 +text-shadow:2px 2px 5px black;
  161 +color:white;
  162 +}
  163 +.submit-button:active {
  164 +border-stile:inset;
  165 +background-color:#4058df;
  166 +border-color:#4058df;
  167 +text-shadow:2px 2px 5px black;
  168 +color:white;
  169 +}
  170 +#cancel.submit-button {
  171 +color:#682830;
  172 +}
  173 +#cancel.submit-button:active, #cancel.submit-button:hover {
  174 +color:red;
  175 +}
  176 +.form-field {
  177 +border-style:inset;
  178 +border-color:#6080ff;
  179 +background-color:#6080ff;
  180 +text-shadow:2px 2px 5px black;
  181 +border-radius:5px;
  182 +color:white;
  183 +min-width:20px;
  184 +padding:3px 3px;
  185 +}
  186 +.form-field:focus {
  187 +background-color:white;
  188 +color:black;
  189 +text-shadow:2px 2px 5px #6080ff;
  190 +}
  191 +textarea {
  192 +margin-top: 8px;
  193 +border-style:inset;
  194 +border-color:#6080ff;
  195 +background-color:#6080ff;
  196 +text-shadow:2px 2px 5px black;
  197 +border-radius:5px;
  198 +color:white;
  199 +padding:3px 10px;
  200 +display:block;
  201 +font-family:"Courier new";
  202 +font-size:11px;
  203 +}
  204 +textarea:focus, textarea.ro {
  205 +background-color:white;
  206 +color:black;
  207 +text-shadow:2px 2px 5px #6080ff;
  208 +}
  209 +div.section {
  210 +position:absolute;
  211 +opacity:0.9;
  212 +display:block;
  213 +top:70px;
  214 +left:170px;
  215 +right:15px;
  216 +height:60px;
  217 +font-size:18px;
  218 +background-color:#101850;
  219 +color:white;
  220 +font-weight:bold;
  221 +text-shadow:2px 2px 5px #000810;
  222 +border-radius:15px;
  223 +padding:0px 15px;
  224 +}
  225 +div.hint {
  226 +position:fixed;
  227 +border-style:inset;
  228 +border-color:#a0d0ff;
  229 +border-radius:5px;
  230 +background-image:url(data:image/png;base64,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);
  231 +background-repeat:no-repeat;
  232 +background-position:0 5;
  233 +bottom:33;
  234 +left:5;
  235 +right:5;
  236 +min-height:70px;
  237 +background-color:#a0d0ff;
  238 +padding:0px 0px 2px 55px;
  239 +color:darkblue;
  240 +text-shadow:1px 1px 8px black;
  241 +text-align:left;
  242 +}
  243 +div.clear {
  244 +position:fixed;
  245 +top:130;
  246 +left:155;
  247 +right:0;
  248 +bottom:115;
  249 +overflow:auto;
  250 +}
  251 +div.login {
  252 +position:fixed;
  253 +top:142;
  254 +left:30%;
  255 +right:30%;
  256 +min-width:500;
  257 +bottom:105;
  258 +overflow:auto;
  259 +}
  260 +pre {
  261 +display:block;
  262 +font-family:"Courier New";
  263 +font-size:12px;
  264 +}
  265 +th {
  266 +text-align:center;
  267 +font-size:12px;
  268 +}
  269 +td {
  270 +vertical-align:middle;
  271 +font-size:12px;
  272 +}
  273 +td.cb {
  274 +vertical-align:middle;
  275 +font-size:10px;
  276 +height:14px;
  277 +}
  278 +td.ok {
  279 +height:24px;
  280 +width:25px;
  281 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAB41BMVEUAAAAAgABXynkAdhdatmFPr1MFfwAAewtZu2ZZu2ZWumRAxGggliEGgwAAlRQApS0AlRMArTIIewAAnBoAoScApTAAZgAAVQBZvm9WslxWsltOtVlMtltJwGpJsVRItVpIrEs5oDYlsUolmykgr0QArjQAoCoAjAQAnSIAjwD///8ClxUDlhMmozM7x0EMmh38/PxKy0wzvjsCnCICmRoEmBcDkg/y8vIFrzcBpCmm3LQxq0MusDkAqC8Apy0KoCkCnygCoSQKnCIYoCAOnCAAnB4Hmx0DlBHs7Ox1oH0urzkHqjMjrCwAoiocnSgHnCYXlyYPlh/3+vfG5su/w7+s37mb1KB5on8oqEAppjo3uTgOpzIlojEJqDAlsCoQoCUOnCQhoSMHmB0IkRT3+/f29vb19fXp9uri8+Tj4+Pb7+DZ2dnP69XIyMi64sS84b+y37u3ubew1rSf06yqqqqfrqCJ0JuXr5qJ0JmSoJR2y4yIp4xwt3hnv3JnxWxPu2thnmhhlWhYumZcm2Nao2JNomJVsVlQnldMnlVJjlJGuksprUhAkEg8qkU+ykQ6t0IsqD8zlT81wD4YqD4xsz0tsDgYqjctvTYCrjUPqjIjmDIUmiINnR8SoBwSlxgIlBgLkBd8M8BNAAAAKnRSTlMAAugG/M1IEfbz5qyGbWldVlBBKyASCgPx5OTIw76+u7udioqGa0M+PBmTh5YkAAABkElEQVQoz4XRVVfjQACG4dBtyy6yLL64W2ZKQ2OkpU7dcXd3d3d395/KJOUEDjc8F7n43jOZi8F+EhIfHS6RhEfHf5vjJM1Wc3u72dooif2y/4q6NzeUCBqeb/JCxD3b0nJSjBzsoE9La1rix3+iKPeFCjmtrVq5VancrbnBEKd/uSpDro+n2Rq30+k0n+ULB/4zXoVgd7iixtvUpPDCMP6aUBOjLEeeHubtvctAidg0hSj8gzaGsUE6sD6IjwY63zoZyCj/opABAIAQvh5VEV0TW5tre34bhKko/AE0HfD7z6dYHCdYO9u/BGjwmw801bG/ODtux4P6NgAlhHTKanKwBIF/qKyjrCCFv5wmfY5utIjBQpr4y4uUPp+j5zOMkaRFU4AhUou+lhD3ijnSQIUl8CH20bA9qVaPDAh16NBAKuSYIKKD83g8l6sz6upq9UKjoS0HC0qUmTiXS6vT6VzNOi3XlhkqPkhWvVFbyrvTGusj0C6SJ2v0Ro4z6jVJ8uADiodiImVSqSwyJgH7wTvKvGKP1m610QAAAABJRU5ErkJggg==);
  282 +background-repeat:no-repeat;
  283 +background-position:center;
  284 +}
  285 +td.check, td.almost, td.enough, td.perfect {
  286 +height:24px;
  287 +width:25px;
  288 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAACVVBMVEUAAAAe5i4AziEApSwVnUF4/XwGkitf+2UChyZ4+4Bo924KgyoEfSQAlARc/2EKmzmh/qlX/m6g/qIJsD8KnzwM/hAAsicA3R47/UEA1R0A3i6A/YN+/YMA1S6U/Zab/aEo/ElM/GEPtkEElikAoiYAliYA8BYA9hJd/GIAsSEA5ix3/H0FzjRG+15s+3le+2MAqSMAvR8dqkcI+hkA6BocnkYA6iwK+RgIvjgA3hlN+lUAwhww+VAgsUoAnCUgmUYn+TEA1RsD6ioNsjsTqz////+o/qyR/5gC/xK9/795/34AnzIAsSsA8SYA1yGR/5V6/4Z5/4Jd/3Ba/2I3/1Az/0AApTEA4jAAqS4AyCYA4iEA3SEA+h8A8BsA/Rr8/v3r+u6p/q+S/5xc/2tc/2c2/0gBxzgv/zcAzzYAtTYDoDYA1zUAuTQAsDQAvC0A5ywArCwA7ykAvCkA2iYA0iYAxSYE/yAA5R8A7B4A9hoB/xcA/hP7/vv6/ft6/4pj0HxQ/Fo51VkAvjcAqjUApTUAsC8Asy4AxCwAtiwAvyoAwSkAuCkA3SYAwCUA+CMA5yMA0SMA9yEA6R0D/xsA+BgA+RQB/w4A/Q0A/wLw/fLJ9NK6/76l/6eU/5542ZCF+Yx9/oBbynZl6XVe2HVT13Vc0nRb4XBj+Gtf72tB22ZIxWVX82RV6WNL2GM921o/41kvz1BA9Ek47kg0/0Uu5kMJqz8Kpj8Jvz4ArTcG3TUAwDUB4C4A4S0AtioAzykAyikAziYAyiYF+yUA0iUA9CIA5hsA8ho195xdAAAARXRSTlMAC/7+r6CWZl1SIyAJBPz8+fn4+Pj49/fAv7y7u7u4t7e1tbOzs6+vraWgn5+enZ2amZiXlpVoZ2ZmW1hST09MMzIkIwqdu/PUAAABsElEQVQoz2IgBBi52LVlpFnZuRhRxTnl3WZ7gsAcOU5kcT2BxMRENwgQYuWFiyvOTUpKcgcDfyDQgInr1tUFAEEgEHiBwAJ9iLiNYBAQJCcnp6SkBAcHNzQE81mB3aMQAgSpqambQ4EgfXX8/PR0CZDbnA6VlZVNnlxV5QEE0zfOdF0+Y4aoA1DCrG9iXwwQxMXFVVVvSnBdMX3aNA9zoIRWYWGhLwgcmVi5xdV1zdS46moPY6CEVDgQ7NyTn5/fv762ZlFsZeWUKVPVgRKAyWZnZ6+c1Vi8u2ddguuy8oqK2NjYY2pACZ2MjIwl8TWNJRtcXddGR0WV90+aVGEClLBIS0trnxefUO9au/hwcXEPSO6oJVDCeXtT0668eldX16WR+0pK/Pz8oqPFHYESLkqZmTk5OQtdV3W2R+4/eGDCBD8/SXDg2wrvyM3N9CnoyMvr7CotjWRiYrKGBJbR1pbm5tzWtraO7qKirt7SSENY8LJsy2oJC4soaPXx2dtd1KuJiChTkSxvb6BURIGPj5gBL1IU2rPwA6W8mSOYVexQI52Hm4NNWZWNg5uHULIBALcOlKJvvIoTAAAAAElFTkSuQmCC);
  289 +background-repeat:no-repeat;
  290 +background-position:center;
  291 +}
  292 +td.nok, td.bad, td.notenough {
  293 +height:24px;
  294 +width:25px;
  295 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABv1BMVEUAAACTJy2kLDOrMjiSJCq3OkCPIympKTHVUFaTJSrTUFauLDPIRkyrLTSTJCrHRUujKC+UJSueKC5hERZyFx28PEGXJSvZQEbLNTzTSlCcKC7IPUSUJCqzLjXVU1i1LDOvKzKyKzLNOkHOQUeeJy26Lza4MjmrKjHMSlDIPUPHP0W7MjirLTSbKC60MTi5NDuUJCqSJSuPJCq0MTegKTCjKjCnLjWOIymvMjiQIymMICVnFBlcEhfAKzO5JzCpJS3HLzeyJS6tJS2lJCzOMjufJCubJCvVN0DhQ0qXIyrpTFLcPUT////lSE+SJCmPIyjsUVeUJCqSIif+/Pz79vbsV1ygJy6cJy78+fn47u7qqazMgYXlcHXmV13mUFbJTlS+Rk3lRUzjREvZO0KuJy+UIiixHCaQGyH8+fj58/Pft7nloKTSnqHhmZ3ckpbQkZXWi4/ShIjAdHi5bnG4ZmraYmeyX2ToXmPhXGLWW2G7WV65VlrRVVrfTFLnS1LaSlCxRky4REvfP0fSPkXcPUWwO0LVNj7PNDyqMzmeMznVMDirLDPPKzPJKDC0JzCYJizCJCyjIyuoIiu7ICmqGyRC316rAAAAPXRSTlMADAIgj2A97uPfysmnoqGYimJOEA0H/Pny6Obk5OHg4N3b19PPzcrBv7+5ramfm4WFfn51a2NLSkdHIhIOijmOJgAAAUtJREFUKM+F0VVXAkEYxvF16Q7B7u5uJRQkdHeFpbvB7u7u1g/s7OyChyt+V895/2euBimkaEwm5POFshE1mnfm1By4bIDLVc5R/99Z4pBtLivcwcrd20IxHMdj8ThOOW9kSpE4bAGuD4PBMwvUroKBczFPefYvYnsJat2W9sIHlQkz5dWPYUf3ZqhhAgTljRF6W8GwU3o+lA2C0GPUQ59rDiyiZ3SC0KKh/aw7HBENoxmEai0tvel1RrWMWhDqpmnpLacvyuz3ehBaZ2i/Aa/vitlJEQjypA76vjs+edExJCBwdQbo63Ij8Gig8YZBQJtmacsYtu2GyyCapMK42wStLjl3PXDxhhAKyjZZgdTTzr7HSnFLst8kLUmRBEFmMiRBklZPV3HuA/uqCGIBsn9UyOGdho5KBQRhBwTdSiSPiqsYYLP7FdwppIA/M91t59KIatsAAAAASUVORK5CYII=);
  296 +background-repeat:no-repeat;
  297 +background-position:center;
  298 +}
  299 +td.ed {
  300 +height:24px;
  301 +width:25px;
  302 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAACRlBMVEUAAAAPGCQAAAADBAYqChEOFiAxNUUBAAAFAAAHDAyPHx+dRVtUQzPKQESdssyWrc1YHiI3MzDefX1VDBGpMjEAAADbdXgOFyETHCcCAwQQGSYAAAEAAgEAAAArCQkBAQEAAAAmNkoBAQFHV2shBAaYJDD///+gttPU4O7j6vXc5vLY4vDO2+zM2evM1eG8ydr9/f7f5/L8/f35+v3v8/jR3ezE0+X1+Pzz9vrr8Pfn7fX1lhb8rRXS3uz8ryTn5+a2xtutvdGUq8q8v7+Lor96kbCIio3vjzf5qx77rR3Zcwr5/Pzg6fPk6fDj6fDL2evAzuCetNKpuc2Zr83g3Mlzi6rQyKmem5WMkpX5y42Qj4t4fYf4xYN3eXxydHZ3dXVbWlprRir8sSjniCjhgiggHhrWbgbv9fzo7vbs7fPd5vLw8PDr7O3N2uzh4eTa3eTI1OTQ2ePw6968y97H0dzW19rR09auwNbMz9Kbss/Nzc23wMumtsvy58qNpsqltsno4sjFx8ePpsT+w8OstbyGnbuDmrnVzbf3t7eAl7axsbKdprCPnbCnqKhwhqdthaWfoKGOlZ/60p5ifJ3MuZuampvkuYjuh4f2hYWBgIHAgICAf374wnrnrHi9dnW2pG+kmW5QWmekTV2UhVdcWVPVq1LeUVF0a01tY0dfTkJuYkGPQkHqkEDEQkBFRD+3iz7YiDu1OztCQTrBOjjoqDNlSDDxiy7opCkvLijmhydtRifigCHHdCBmPSCTHSD2lhb/rxPDaQ7I9twOAAAAJnRSTlMAoxaUBKVPNigc/vr5+PTv6+jn3NrPsrCmpZyakIp1dGhVTT0sF3ISilYAAAF3SURBVCjPYsAN6tQRIJBfmQUuEehXEKAPBSbGfGxwicosf38zMAhw8FUzcGJThWoKNtSFglyghJoRN68YJ0TCRwcGHPwMvBetndEsxAHS5KRpamoLhECyuLw+wnlWx/RlIipgCQ04sHVrdI6bt3EzlxxQoilDGwby12zoip8ZsXqfsAJQwsVSCwa2JcdsiZ7QGy8gywGSMDEEA58895Q5dge2h88WlGEHWd5qogkB7skxSTYe+/fwSIPFGQBrs7ACAXv3lEg7G09rr72iShAfdppbAkHm3J2RQPXWaYkLJTkhPnc1NjExSZ+2exJY/a64HmYmqISRhYWFfdgUO7D62ApHuISaubl5SHvIUqD6rbFlFnCJUDVjY+OGorAF6w+udCs1N0aSMFKL2lQ7f/GqJVPtvY2MgmASfWoGajtSVyxPcHPOMQACuES/mlp46rqEqKpsIzUQqIFJTC7Ua5kY3V1dogcBLjAJRSlxVlZWRjiQkAdK4AEA+il2ExPxslwAAAAASUVORK5CYII=);
  303 +background-repeat:no-repeat;
  304 +background-position:center;
  305 +}
  306 +td.some {
  307 +height:24px;
  308 +width:25px;
  309 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABDlBMVEUAAABSUmZPT2xSUmpLS19ZWXdQUGtQUGlbW3VOTm5NTWxOTm1eXoNUVHVOTmxdXYFgYIRPT2tQUGxZWXRRUWU/P1BUVGg3N0RUVGZfX4ZsbJdkZItubplbW31mZoxfX4BQUGxbW3pRUWxXV3FSUmpMTGJUVGv///+dnd6Li8RgYImBgbZlZY5PT3CFhb1qapZaWn9WVnpUVHeZmdmUlNJ+frNoaJRcXIKIiMF6eq2Xl9Z8fLCTk8+Pj8yCgrheXoWjo+eenuCbm9uOjspubpxSUnT6+vqamtqWltSHh7+EhLt5eax3d6lzc6NsbJpmZpGNjcd0dKRxcZ/29vapqe+mpuvW1vK4uPChoeRYWHweFNUfAAAAJ3RSTlMAGuZ+M8nIlnD79vLx8e7r493OoicdFBQK+fX17+nm0dHDw5aJiWtudu4FAAABd0lEQVQoz4WR51qDMBRAa7XDvbXuLZAQCIRQNqWF7j0c7/8iXmqt+qvn5zlf7neTZFaxVsztyPL+Q3Htnz49vsROBXDw9dP5r9/Yt5i4gEkHG0tPDYexRhVoMMfxbk8Wc258w3CcahRFIms2DcO6+w7Hbs33jKaQMhE9z/ftwnyfq5aUFmFO3fBrknSRLlCMFUsa1moRa3xAYUPJUjovEHKdAAowbHl1QTDAYzcHYdfmgdKyLAk34MBUUdqB2z2AoHU7HLcVBTPwM9xuY7cz2oGwafZsl+MggDlNO8DctXvmLoQ9Hakjm3OlLkwx59zuqaGehfCYUDRQ47E7EWbd0ThWB4gmeQiv5DOUTbVvjrux2u+rphxqZD294J5OEZSe+B7FqUdU3yplgALRykiWW7CUbYIvzw8AZ4cJFKRW3sTBYO6Pfp49SzQahmWZIhRSjRwuf/HknugaLQNU08kR+CWFTZLoQEK2YP5fzp7z2e3tbH69lFnBF01/TOuZl9vyAAAAAElFTkSuQmCC);
  310 +background-repeat:no-repeat;
  311 +background-position:center;
  312 +}
  313 +td.del {
  314 +height:24px;
  315 +width:25px;
  316 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAACGVBMVEUAAAAAVbYAS9ILKTcAUKAASqsATp0ATacATaMAUrMACiEAYcIAEyUAWcMAFSsAQ6MACgoAIkoAXLY4xgAAKFI0wwAAK1UarwAAeesAKUwAK1kAIkUAdeYAdegAIkgAUqYAHzsABggAWbwAHUAAfnQAS8UARY4AEyQ3xgA5xgA2wwAAGzUAIEAAIkIAMGQwvQAANm8AOncAee4AUaMAU6Y3xgAAVaoAUKIAHDQAT58AR5EAceIAKE4ANmkAMF8AGjkASq4AQYIALVgAJ1AAN3AAIT0AMGIAijsAVa8uwgAAd/QACxUASpMAeeoAjCgowQAAa+YAJEQAemwAGDAAcvwAYrcALF8AJUsAb4wAiTIAhf8AJEkABw0AHDUAFDsAWU44xgA4xAA2xgAAGCwANWgAFSo0wgAuvAAAJUcAQ4AvwAAAT50ADRkARIgAM2YANmkAVq0AQIIAKVQAIkcAGzsAXrgqtwAAducAXrkAChYpwAAATJgAR40AI0wAbtkAQIAAduULowAAa9MAJD8Ae/EAI0gpvAAgsQAAIDsAeO0ATqUATpgyvgAAWrUAfO4AY8IOowA0wQAAChEAZ80vvgAOrAAAQroAMFgAKUoRpwAAeVYAXsAAZdQAOm8AO3sAYbIAgFwAHzkAQY0AAAYsvAAAaJEAhSMARIkAVcQABwcAZ+MAMFAAGiwASbYAkgkAO/8AijUAqiQAQOD80Dn4AAAAs3RSTlMAJAoDGyJhIEofBikjGhgSCU0t1YVqX11cWllRTkVDQTg0MismIyAV3s6mm5WQiIV9cnFsaWZhYF5bW1NSUE9NSUdHR0NDQj48PDs6ODUzMzIuLSopKCUlJCMiFRIRDQuurJ2XkZCPiomGfXp5eHh3c3BwcHBvbmpqamloZWVkZGNeXV1ZWFhYV1NSUlJPTEtLSklIR0dGQD49Ozk1NTQyMjEvLi4sLCknJiUgHRwcGhgVCIB3Y5gAAAGgSURBVCjPYsALmJnjw2dIt0pKStrIBcYyM8PEo+3yM7MrmqxlZGQn91oZ5omFQ6S4igqMjMobJKxlZL18Q0KiovpT+CASIrmldRISLZ19QImAgDmzOfR4IBIltSJ6Bob1Vt0c8h5KQj6OLsUxEKvtV4e5SYmJSdm5zFvOzsLPz9QsAJFQUGZiYVFTYwUCdnZ+JiYGCy6Iq3jkgBIsnJzsrIyMjEAJpg6og/kEgRJAYVVGv5lZnvFMYa4wCWkmoHpWRtUJwsKipks2TQ+GedCefy07UHy9uLB+5BT/jYJroBKAxbmq8bIzMqqI64sHBa0T9RTkg0pwKczlZWQMXaCl0S7EvcHUX1odFlgL3YAS3O6a6ZF+ET0TlwnGwiSUnUASS8sSNRPakqoWyQnAJIKBEqHc3BFpGlpTRVUcFeDhzuPMySgkNF9pVqP7CpVVtoHwiFJ39pHnAAKHaQ7AYLRVhksI2NSYs0GApWWXFA8ibr0zDKrNTIyNTczMC0Us4hASAoqVqdo6uro62sk5k6C+gHkyhmexorfiSj4BZgb8AADrIlTIFASIAwAAAABJRU5ErkJggg==);
  317 +background-repeat:no-repeat;
  318 +background-position:center;
  319 +}
  320 +td.view, td.preview {
  321 +height:24px;
  322 +width:25px;
  323 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABgFBMVEUAAACybgQ9erjEfwwMV6TBgBE4erwWX6cyc7RMh8K0cgS5dQhUicCvbwKuyOg8eriscg14SzURW6XSjh4qb7LUjhfShgZIgrzjjgJqc2Vpb1/Mihslaq00dLTQkSgpbLA9ercmaa47ebk0d7gATJxCf77BfAq6dgi6dgVCYW68dwi9egpMhL06eLW4dgceZaq6eApOhr4+fbm6eAtdkMRCfbi6eQ24dgxVi8FFf7uDqdJynsu4dge3eApLhr+00ueqbAA3drpkl8Xo8v7C3fu62fqp0Pjc7P7P5f2y1frJ4vvZ6vzu9/8kaa33/f/m8f33uVLlqUXq9P/Y5/fP4fRwo9Z3pNE9e7oeZq35v131tEf0sEDzrjryqC3toSLtmxD0+v/x+P/e7v673P7K4/vT5vnB2fK/1u2jxeiSvOaqx+SRtdmKsdd/qdJsntBfl9ByoM1hlcpPisWCpMRckMQ4eLkwcbLxtVD4t0vlpj3jojb0rTXlnyrXlSjuoBzgkxJ4t3KIAAAAQ3RSTlMAGPTu6NfFvWZfXEg6LhoSCwT+/vz6+vn59/Xz8vDu7efk4N7XwcG3rqqpnZeWkY51cm5ta1JNTEpCJycnIRgODgwGy8ozJgAAAPpJREFUKM99zmVvQlEMgOFiY0MGzN3d3f3A7uQq7szdBZe/TgghPeEQno9907RQl2VOLQjC0PpJ1Xy5/919JUovf/pmoK21uEmJk7xq6WIZdjlJmfi1CGjFe8NV3PtsGEaeztB3E4Y2hx15xjH4b8+RpwGDcEr5pMLoswP9UDcaP+4uKuz/xxgOBh+4yzLOO20FaiX+yEuESIT/7e6aMgPa8r+JPH/t8vV0xGIaA6AdvVbd2Tc2DzOFfLR9VgVo17RtOgQ4mohGIlmdERhmTSYcDvUu2JhiaA0Fg8ncHjCW0rIsp4xssE4mAgFlA1gqnaIM7EOtsrqJD7OKPBJCztYjIqEAAAAASUVORK5CYII=);
  324 +background-repeat:no-repeat;
  325 +background-position:center;
  326 +}
  327 +td.no {
  328 +height:24px;
  329 +width:25px;
  330 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYBAMAAAASWSDLAAAAG1BMVEUAAACNAAB5AQB3AQByAACGAAB/AABrAQFqAAFgNiydAAAACXRSTlMA8/T19fPys7EGJ6HTAAAAIklEQVQY02MYDMBUEAyCwRy3QBBbNAXMKTFSAgJlD4bBBgBrrgPcZyYWLAAAAABJRU5ErkJggg==);
  331 +background-repeat:no-repeat;
  332 +background-position:center;
  333 +}
  334 +td.bad, td.enough {
  335 +opacity:.5;
  336 +}
  337 +td.notenough, td.almost {
  338 +opacity:.1;
  339 +}
  340 +td.first, td.firstno {
  341 +height:24px;
  342 +width:25px;
  343 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABxVBMVEUAAAASEhJzr90SEhISEhIrRVqFyulcndZnptRYlMRnpM5KfKiK0euEyOiL0uuFyukgLzyIz+p6uuQbJS0SEhIbJi4SEhKCxucSEhJeoNiIz+qFy+lprNx7u+OIzuphoteFy+lbm9RopNRdndJoo9BhodJendBalslWk8h2tN9ppNFno9Bmo8xQh7Z1s95qp9NTiK+CxOeL0utFc5xtqNVfmbyIz+pZj7J+wOVHcpJzsttOfZsfLjwxTWCL0uv///9mns+DwOaKyel6teP8/v+Oz+uMzOp/veXt9/2IzeqIxehxrt9tptfY7vmT1+2Jx+iFw+eBwud+uuR4suBuqNpxqdmp1/CKzOp8veV1seB0rt9nqt1zrNtdoNppodPx+v3X6/m42fKj1e6S1OyQ0euDwud9uON4t+Jvq95lp9xipNtwrNpoo9j6/P6/4fWb2u+m1e+V2e6i0+6i0e2g0e2NzuqQyuqFy+mKv+eCv+V+v+V2ueNxtOF3s+Fwq99rptlspNRro9RnoNDm8fvO5vfB5PXI4/Ws1/CW2u6R0uyL0OuXzuuRzeuNzeqSyeqEveWGu+R5ueOEuOJ1tuJzteFqrd5inc234DQrAAAAP3RSTlMABf5CC1gR9N7Hu52cb2ZOR0Y6OTIpIBwY+/n59vTw8O3t6OXl4N7R0c/JwrSwn52dnJCPjo2KgX5zXU9OLAaavyVQAAABoklEQVQoz32PRVvrQBRAmz6K60Ofu+DuEiaBhgjE6y1SF9zd3fX3cqdFN5zFLM65881cwyNdedl1mdk5yYbXJDd9ZVn2iGU/Zha/9Hnf5wcmB4DJg/lPWc8+y896fb1xDr0+ufbR5yxZe81mM0VRcM76vHJLwhd/8WMpHk+JokhZTk6ttvfxUBWkRI7jRkZJC8f1k30UxZTGP2SUJD9C06MkuS8NkWTfrMTZ8ZW2KEKLizM9JDmGwA+OWxEyNkCojjKMMg1+9/zBM8xqGYT0aEBZwPPMHvg5xASUgPobQrlAK2cQhukdeGCBxhh/QqjYUmnZgovSD+VCVVW7ngqh8c5lpOUJXBAuVw6XqzsdQrtT112rSyNQJiQo2w5djzVDSEqNCYJmt0GZssmwoF1Y/9xpAFqd2saGwF/OzQQdQZsFOQRnDYFDSVpY83g8Gs+HNjfX+DUt/KcQNJD/N8J7uh/YCoW/mYhEIHL/RVb4daxjoevIL1MSyETJz0hxO1eWl29u3R8qc8E/UdRRn/bD7U75n2EqJAwvIUoK3gEFRTD+NvetwnhfPecH4gAAAABJRU5ErkJggg==);
  344 +background-repeat:no-repeat;
  345 +background-position:center;
  346 +}
  347 +td.last, td.lastno {
  348 +height:24px;
  349 +width:25px;
  350 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABuVBMVEUAAAASEhISEhJdn9krRVofLzwSEhKFyukSEhJzst+HzepcndZcnNNopNJfn9FnptRYlclnpM5KfKiEyOiL0uuIz+ofLDcTFhiCxueCxOdprNx7u+OIzuphoteFy+l2tN9ppNFUkMNcmMVno9Bmo8xQh7aIz+p1s95qp9NTiK+CxOeL0uuL0utFc5xtqNVfmbyIz+pZj7J+wOVHcpJzsttOfZuL0ut/weZ7u+R4ueMxTWAkN0USEhISEhISEhKL0uv///9nntB6teKLy+l3suH7/f+Oz+uJyelxrt/a7vmMzOqIxeiGw+eCwOZ/vOV9ueRzrdxuptdrpNSGy+mJx+hvq99xqdprpdiU1+2S1e2Q0eyJzup/veV7vOR3uONys+Foq96o2fC11/Cn1O+V2u6l0+6CxOeDweZ/weZlp9xoodLu+P3r9fzq9Pzl9Pvi8fvc8PrA5PWn1u+e0O2WzeuQy+qEwueFweaGu+V6t+N2tOJ1rt5uqNthpNtwrNpeodpvqthmpNhlnM7Q5vfN5ve63POs3PGa2O6h0+6W0+2L0Oudy+uTx+mKwOeDt+J1tuJmqd1jpdtinc2DobtnAAAAQHRSTlMAA0L+WEkfEQn9+fTp59/e0budb2ZGOjQc/Pb08PDtz8nIxsK0sJ+fnZ2cmZCPjo2KgX5zXU9OTjw5LCsoFA8GGATzoAAAAZ9JREFUKM99zlV34kAYxnFYoN3K1m19t+7uOoHQpDEiJcGhLcXq7u4un7jvhEPlpv+LuXh+c+aMIdVIcVFjQ1F3uuFj6a2/vIr3WvFmVpe934v/KK6wy+1yhcNKZuHbXvhdcXtG9TxuT6Q+tffEbKMMY9NjgGLtyb3sZ4Sh1ibGoctVirIxNn+vDjUBapydR2MsN4XsUyxLUb6/+ocyOG6dmkdoDADZp9c5js3oA+jcj/I8czEDsrGEheejYjNA7aFPEHjvFRZWF8FH/gPI33dAguNuFqFT4QwhdCuQ3wAqJKveJsCJdRJg1SFiqCRI3OYcPIV3+zlvPcwFaHkWxZ2de7xv4X0iZhWJfICukKqq4gJCi9EbvPtIVT1qAxjOPZKk7QW0GPGvIPuyn5Qk7Ue/AeoI7crBjWX/Nr21shagZVl6rDNiGCqP78pO2inDQWuJhBbPGTDoleQ80QkilTP+22xMgtGStxekNeL4mNCcD3vZ5q8wJqWkIOsgFAwEgqEDU5UF9ldJszT9zzaZsvIKzIP4nfdU+gUqTYPrn/cCD9B3xI0Q9tUAAAAASUVORK5CYII=);
  351 +background-repeat:no-repeat;
  352 +background-position:center;
  353 +}
  354 +td.prev, td.prevno {
  355 +height:24px;
  356 +width:25px;
  357 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABnlBMVEUAAAASEhISEhIfLzwSEhKFyulcndaHzepfn9FnptRYlclopNFlo8xKfKiEyOiL0uspQlaFyumIz+oSEhISEhIbJS0SEhIbJi6CxueCxOdeoNhzsd6Iz+qFy+lprNx7u+Nhotdbm9RopNRdndJoo9B2tN9ppNFUkMNcmMVQh7aIz+p1s95qp9NTiK+CxOeL0uuL0utFc5xtqNVfmbyIz+pZj7J+wOVHcpJzstsuS2FOfZt7u+R4ueMxTWASEhKL0uv///9/u+Vnn9B6teJ4suCDweZ9uORzrNxtpteKyumJyOmGxOeOz+uCv+V1rt9rpNSLzOmIzOlxqdpvqNnt9v2U1+2MzOqDw+d3t+Jxrd+S1OyP0Ot/veV7vOVoq95dn9lpodLx+/294fS64POV2u6IxeiGu+RytOFlp9xwrNr4/P7m9Pu53/Olz+2KzuqSy+qFy+mAwuZ+wOV2ueN0s+B2sd9vq95fo9tkpdprptloo9dlnM7E5va+3vOz3vKe3fCa2e6l0+6X1e2L0Ot7t+Nmqd1uqNtqotNnoc9inc0eCz8NAAAAQHRSTlMABQtJHxH079/e0b+4nW9mWU5GRUA5Mikc/Pv6+fn29PDt6OXlz8nIxrCfn52dnJmQj46NioF+c11WTzw5LBQGie+1rQAAAYpJREFUKM99z1VDg1AYxnFws7u7u7trbOA5DB0wlFirm9vs7m6/te9hzrjxd/Xy/LkAKmm+KH+gP78wlfordSRdlnefZLmmq+L3XpS+vxJeAeHwfm3ez55XKXu8i4TX4/Fqfcm98FBaVFWJ53lJUqEdjCX2inpN5Z3E+ubWHi+pvH/aDN260xkRwJrNZruVIk7e12p+ULUgaBxYh331kdcEIXI8A2EiznFLYJvsd7twcxwagtAT9zHghuz38hK5fWwbhOz4AtiBfXmPYxZMbAsJ2OFwMA8kbDi+oCYIOe8nLMto12ZhTSdKJoThD4RcLt/BmllcACF7DoSpgNvtRuj50CwsQvB4PgohJfMSY0VRdD/5kR1DwfiibpYC4wFFFDHGx/7tzS3GgPullyZhriP2Ggq9iaJL9+uGGMKxjHLKVJpxboTsSaexhkk6EWhL1lnUuLBfXdkvT/Wz5oIUGBOlNDctGIgeHUUDwapOC+zfrJbB9sZgMC0rt6Ccpn6jrWUlxcUlZVZ4/X+fEgZ011jIKjMAAAAASUVORK5CYII=);
  358 +background-repeat:no-repeat;
  359 +background-position:center;
  360 +}
  361 +td.next, td.nextno {
  362 +height:24px;
  363 +width:25px;
  364 +background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABoVBMVEUAAAASEhISEhKCxOddn9kSEhKFyukSEhJcndZnptRYlclopNFnpM5KfKiEyOiL0ustSV+FyukgLzyIz+p6uuQbJS0SEhIqQlOCxudzsd6Iz+qFy+lprNx7u+OIzuphoteFy+lbm9RopNRdndJoo9BhodJendB2tN9UkMNcmMVmo8xQh7aIz+p1s95qp9NTiK+CxOeL0uuL0utFc5xtqNVfmbyIz+pZj7J+wOVHcpJzstsmPVBOfZsfLjwSEhISEhISEhKL0uv///94suBnn9CKyel6teJ9uONup9eHxeh/veXl9PuCvuV/u+R1rt9yq9xspNVpodKT1+2Q0OuNzuuNzOqEweZzrdxvqNmLzOmGy+mFw+dxqdqKy+l4t+Nxrt9spdjc8PqR1eyIzuqJx+iFwueCwOZ8uuR1teJxtOFwq95nq91lptxhpNv8/v/1+/7N6/jF4PWV2e6Q0uyL0OuLw+h+weZ7vOR2ueN1sd9eodpvq9lno9ZlnM7o9vzR7/na7PnJ5PbC5PXH4fW/4vS82fGW2u6MyOlqrd5pqd1inc3fzcNaAAAAQnRSTlMAA0L+/h8RCfTe0ca7nW9mWE5HRjo5Misc+vn59vTw8O3t6OXl4N7PyMa0sJ+fnZ2cmZCPjo2KgX5zXVlPTigUDwZQTPziAAABkUlEQVQoz32PZVcjMRRA223p4rqwrC/u7g6dCc0M9XGpC1Xc3e1X80KZA3zhfnq5Ny/nxGSwVFc1PFRVYzN9xDb+N6bGdtTYz97G977uv+rf8gNbd+qvyjdfaVGjHMfzPMdt+7ctg4av2VN4QVAQQooi8Fx0b7LgG/9YBJBXaxEhHkcoIAT2v72EviCKMwyzbrev3DMAQmwH8bYfmpYQRX7DDmVXFBOaxhySlWmPmHQ6nUr0nJQEjElRGoXQf8yyLiCwU9hxsSxLlUEoP3asOgguxyWUCxccqVYIZXjZ4BpCxAmD1Ayhm6Ze2QR/xrEUdYhLIIw9SZKbQPxKgKXckkSXQ5h91HUPcEs8WnV7dF0/mYCwWHKCsSxnyAe1oEeWMQ7//m4CprKy1+tN3axFkimMYcTZATMJC1052ecLBfeDIa8PCOfaYIFQ354P+WiDTO5ftbkQzLWl+XQoTJ+e0uFMKt9S/RVkodRXFB9l0wcH6Ycja08t8UYpmhvpbLJai0srZubJO+9TwxegoQiuf84zATd21V0d5SoAAAAASUVORK5CYII=);
  365 +background-repeat:no-repeat;
  366 +background-position:center;
  367 +}
  368 +td.nextno, td.prevno, td.firstno, td.lastno {
  369 +opacity:.5;
  370 +}
  371 +td.preview {
  372 +opacity:.3;
  373 +}
  374 +td.empty {
  375 +height:24px;
  376 +width:25px;
  377 +}
  378 +td.ok a, td.nok a, td.ed a, td.some a, td.del a, td.preview a, td.view a, td.first a, td.last a, td.prev a, td.next a, td.check a {
  379 +height:24px;
  380 +min-width:24px;
  381 +display:block;
  382 +width:100%;
  383 +text-decoration:none;
  384 +}
  385 +td.nocap {
  386 +height:130px;
  387 +width:320px;
  388 +background-image:url(data:image/png;base64,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);
  389 +background-repeat:no-repeat;
  390 +background-position:center;
  391 +text-align:center;
  392 +text-shadow: 0px 0px 7px #000000;
  393 +}
  394 +.disablestamp {
  395 +color: #FF0000;
  396 +display:block;
  397 +font-size: 28px;
  398 +opacity:.5;
  399 +transform: rotate(330deg);
  400 +text-transform:uppercase;
  401 +letter-spacing:3px;
  402 +word-spacing:15px;
  403 +font-weight:bold;
  404 +}
  405 +.whitelist {
  406 +opacity:.5;
  407 +}
  408 +[type="checkbox"]:not(:checked), [type="checkbox"]:checked, [type="radio"]:not(:checked), [type="radio"]:checked {
  409 +position:absolute;
  410 +left:-9999px;
  411 +}
  412 +[type="checkbox"]:not(:checked) + label, [type="checkbox"]:checked + label, [type="radio"]:not(:checked) + label, [type="radio"]:checked + label {
  413 +position:relative;
  414 +padding-left:25px;
  415 +cursor:pointer;
  416 +}
  417 +[type="checkbox"]:not(:checked) + label:before, [type="checkbox"]:checked + label:before, [type="radio"]:not(:checked) + label:before, [type="radio"]:checked + label:before {
  418 +content:'';
  419 +position:absolute;
  420 +left:0;
  421 +top:2px;
  422 +width:12px;
  423 +height:12px;
  424 +border:1px inset #6080ff;
  425 +background:#6080ff;
  426 +border-radius:3px;
  427 +box-shadow:inset 0 1px 3px rgba(0,0,0,.3)
  428 +}
  429 +[type="checkbox"]:not(:checked) + label:after, [type="checkbox"]:checked + label:after, [type="radio"]:not(:checked) + label:after, [type="radio"]:checked + label:after {
  430 +content:'✔';
  431 +position:absolute;
  432 +top:1;
  433 +left:3px;
  434 +font-size:10px;
  435 +color:white;
  436 +transition:all .4s;
  437 +}
  438 +[type="checkbox"]:not(:checked) + label:after, [type="radio"]:not(:checked) + label:after {
  439 +opacity:0;
  440 +transform:scale(0);
  441 +}
  442 +[type="checkbox"]:checked + label:after, [type="radio"]:checked + label:after {
  443 +opacity:1;
  444 +transform:scale(1);
  445 +}
  446 +[type="checkbox"]:disabled:not(:checked) + label:before, [type="checkbox"]:disabled:checked + label:before, [type="radio"]:disabled:not(:checked) + label:before, [type="radio"]:disabled:checked + label:before {
  447 +box-shadow:none;
  448 +border-color:#6080ff;
  449 +background-color:#6080ff;
  450 +opacity:.5;
  451 +}
  452 +[type="checkbox"]:disabled:checked + label:after, [type="radio"]:disabled:checked + label:after {
  453 +color:#fff;
  454 +}
  455 +[type="checkbox"]:disabled + label, [type="radio"]:disabled + label {
  456 +color:black;
  457 +opacity:.5;
  458 +}
  459 +[type="checkbox"]:checked:focus + label:before, [type="checkbox"]:not(:checked):focus + label:before, [type="radio"]:checked:focus + label:before, [type="radio"]:not(:checked):focus + label:before {
  460 +border:1px dotted blue;
  461 +}
  462 +label:hover:before {
  463 +border:1px solid #4778d9!important;
  464 +}
  465 +hr {
  466 +size:100%;
  467 +border:0;
  468 +height:2px;
  469 +background-image:linear-gradient(to right,rgba(0,0,0,0),rgba(16,32,175,1),rgba(0,0,0,0));
  470 +}
  471 +.highlight {
  472 +color:red;
  473 +text-transform:uppercase;
  474 +font-weight:bold;
  475 +}
  476 +div.pages {
  477 +position:fixed;
  478 +top:132;
  479 +right:15;
  480 +height:30;
  481 +padding:0px 5px;
  482 +background-color:white;
  483 +border:1px solid #80a0e0;
  484 +border-radius:30px;
  485 +}
  486 +td.pages {
  487 +color:darkblue;
  488 +vertical-align:middle;
  489 +height:24px;
  490 +min-width:12px;
  491 +font-weight:bold;
  492 +text-align:center;
  493 +}
  494 +td.actualpage {
  495 +color:white;
  496 +text-shadow:0px 0px 4px black;
  497 +}
  498 +td.pages a {
  499 +height:24px;
  500 +min-width:12px;
  501 +width:100%;
  502 +vertical-align:middle;
  503 +text-decoration:none;
  504 +}
  505 +div.submit {
  506 +position:fixed;
  507 +top:132;
  508 +left:165;
  509 +height:30;
  510 +padding:0px 20px;
  511 +}
  512 +a.new {
  513 +background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAABX1BMVEUAAAAMNBgAnzEBAAAAky8AuzIBAAAAvjEAdjIAsTEApzIArDAAqjAAty4AhSoAcTQAai4AqzAAyCoAvS8Amy8AaC0AwDEAnDEAhzIAwi4Ady8AuzMAxyoAYS8AUBUAZR4AxS4AhzUAtzMAajAAjTcAYS8AlS4BAAAAZTIDBgEAAAAAoTMAvi0ApjEAtTMAxi0AyCoAjywAvSwAszQAcS4Aci4AmjAAnjEAky0AnjMAqjQApi0AuTAAli4AqTIAgzEAgzAArTEAnjAAmDMArDQAlzMAqzUAZRkAaxoAbhoAYx4BSxYBTBgAsDMAxysAxisArjQBAAAAky4BAAABAAAAdzQBAAAAfDYAnTAAjSsAySoAvDEAwTAAkCwAojEAmi8AlC4AsjIAujMAqTMAxS4AxywAvjEAnzAAly4AtzMAwy8ArTMAmC8AwSsAiioAtTMApTEAky0AhCwAfiwAiSp827BQAAAAWHRSTlMABN1F8RIyMBIN/vLy8Eoy+Pfj397X0tLCwsHAsKWhgnd2dnVdWkUwFxEJ+Pj39fX19PHw8O/u5+fj4uLe3dbT0tG/sK+lpJSSkIF8amFgYFpKQjs1MCAXHLGCHQAAAV5JREFUKM+FklVzwzAQhNNAw9wwM5SZmZnbpHYVO7bjxHYb/P/Tk+Nxk5f2e9m7XWlO0kjzDxPmu6iH4zzRe/PEqG9ILnwozCcNv74xxHLc0OdYIWRUfT8pQPIFsKxAkn4lMUQaJMmyM/HLi/Ml8BtExCDPTdeJRoMU7M/lcslLkgRRb6XxCcxzrToBkX0SFnkJ7LeX8ZZbmm7jSA526mDTNP0AwYlI026b1bpdgODQarO5aVE8g2CLES3xR51OV4LmBfSaYZg9qC0MgxKgKvkOY5kFRajDJ0bfwYE6aBp0E6HK1VjAIxQAPeZ5fk2r1QbeoDmCYp2vVE6hzlaG6PFxp5Qmiy+orwFqUMPoTfhJUpTUbEqSvgDNrtQEqJQ80xTsUsDizVPesUFRXaobfNfIvB5UPzFVRfadGgVnuFdV6YWxr1DMrPQH38Cgv5opjn0GUy7mc7l8sZwJ5v7JD9pHX8JdXH+sAAAAAElFTkSuQmCC) no-repeat center left;
  514 +display:table;
  515 +padding:0px 10px 5px 30px;
  516 +line-height:25px;
  517 +height:25px;
  518 +color:darkred;
  519 +font-weight:bold;
  520 +text-decoration:none;
  521 +}
  522 +input[disabled], select[disabled], textarea[disabled] {
  523 +opacity:.5;
  524 +}
  525 +div.shadow {
  526 +display:none;
  527 +position:absolute;
  528 +top:0px;
  529 +background-color:white;
  530 +background-image:url(data:image/gif;base64,R0lGODlhVgAiAOfEAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQsLCwwMDA0NDQ4ODhAQEBERERISEhMTExQUFBUVFRYWFhcXFxoaGhsbGxwcHB4eHh8fHyAgICEhISIiIiMjIyQkJCUlJSYmJigoKCkpKS4uLi8vLzExMTY2Njg4ODk5OTs7Oz09PUBAQEFBQUJCQkNDQ0REREVFRUZGRkdHR0hISEpKSktLS0xMTE1NTU5OTlBQUFFRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVtbW11dXV9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdnZ2lpaWpqamtra2xsbG1tbW9vb3BwcHFxcXJycnNzc3R0dHZ2dnd3d3h4eHl5eXx8fH19fX5+fn9/f4CAgIODg4SEhIWFhYaGhoqKipCQkJOTk5SUlJWVlZaWlpiYmJmZmZqampubm56enp+fn6CgoKGhoaOjo6SkpKampqenp6mpqaqqqqurq6ysrK2tra6urq+vr7GxsbKysrS0tLW1tbe3t7m5ubq6uru7u7y8vL6+vr+/v8DAwMLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy83Nzc7Ozs/Pz9HR0dLS0tPT09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb293d3d7e3t/f3+Hh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf39/j4+Pn5+fr6+vv7+/z8/P39/f///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQBCAD/ACwAAAAAVgAiAAAI/gCJCRxIsOBAJ1QSKlzIsKHDhxAVOjFIsaJFgwAyatzIsaPHjyA5XhxJciCABSgZoFzJUiXLli9jyowJoKTNkoNMVcxZUdCpioF+Ugx6s2hJ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);
  531 +background-repeat:no-repeat;
  532 +background-attachment:fixed;
  533 +background-position:center;
  534 +opacity:.6;
  535 +width:100%;
  536 +height:100%;
  537 +}
  538 +div.errorbox {
  539 +position:fixed;
  540 +top:30%;
  541 +left:30%;
  542 +right:30%;
  543 +max-height:40%;
  544 +padding:5px 10px;
  545 +background-color:darkred;
  546 +color:white;
  547 +box-shadow:3px 3px 10px black;
  548 +border-radius:5px;
  549 +overflow:auto;
  550 +}
  551 +div.errshadow {
  552 +position:fixed;
  553 +top:0px;
  554 +left:0px;
  555 +background-color:black;
  556 +opacity:.7;
  557 +width:100%;
  558 +height:100%;
  559 +}
  560 +td.close {
  561 +height:24px;
  562 +width:40px;
  563 +text-align:center;
  564 +vertical-align:middle;
  565 +background-color:white;
  566 +color:black;
  567 +font-size:14px;
  568 +font-weight:bold;
  569 +cursor:pointer;
  570 +}
  571 +div.pwc{
  572 +position:relative;
  573 +font-weight:normal;
  574 +top:10;
  575 +font-size:10px;
  576 +color:red;
  577 +}
... ...
static/default.js 0 → 100755
  1 +var link=document.createElement('link');
  2 +link.type='image/png';
  3 +link.rel='shortcut icon';
  4 +link.href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAC+lBMVEUAAACKyO6Yw9MeGC5glcltBAY/aaSCmLs4XZhloc9OAQE0Tn5EVX8hBQ0mUZREbqo6YZaBpdJcBgpxAAAlOmgyUIRqmb07AAA3AwRQZZ3b8vtqAgMzX5UsbbcrW6M/XV+EAACfAAFQfrZGAAA2BwtkodM5WpqJAQJuocqOweDa6e9rkKIaP4BTe7Xr+f1xlK09WZbn9/iz0eQ8XoDT5uR5pqoyUZI6VHF6t+i12e5zr9aQn8FdgYcuYqdkZmo/GhiavLcnQHKlscpamM0PIVcFFEYLG0tRXVQFCzMfS5MPMnM9fMgfP3ckSIQPL2sYKFYtX6YcMWK7AQItWJsqUI81VYguSHp5CAuhAgMsZrUZRIwwUYAlOWYJKGURKV/i5ckJHlNKV051hqolWKU/aKFAXI4YQYM9THNBUUQDCz0qSByZBAZums6Rp8fG2cBYgbA4aKtTYogsSoYSN3cZN20CBCkwSyYlRBisAwRBbrAKI1tNVUcyFyqQAwXIAADx89jl69fT48g4dcAhUp1zhIUSOHwvO1giJEY9KkMLEzphFxtNCQl+qtttlMJUhL1OfbdLdKxObp5FaJUzV5BGZDY0VCNOFyCS2Pjm9PdDerg6bbfO2629y6tkfKUqPW09UzKEBgjR6PNfrO309ufm8OdWmeFUjMvU2r2xw5sxRjg/DxwrThqo2feDy/bI5e6ryeZEhNNjhbi80rVljK640I+WtIJkd3csSHGLqWvPAAC42+WFuOSy1dOtyKuhwZhkd5ZcbZJMSmNpb19+q1xbY0BpMT1SJzQgEy4+XCnN8f254/RwufFzruSa099intsvbsBTd6J3ipBwf1WAIShxHiEcCSCKERX2/f6WxemlvNmCwM3d4bjB1p+ElZqouotdfYqsyYl2nnNValtNbTxSMyHU6NpvotCX0r13sbyUnZWhxG5FNlFBSzZ8xdxKkNmhv7WcqKx+tZuGh5FrfX+Fs3ccNhFRdZOPkYJ6f2krPSIiPhtxmFsmNxWjIiSCxoH+AAAARXRSTlMAChsN/v5Q/v4t2yn9HOF2G/3957eLaVw9+/XKxZWR+/Lxvrl5Sj3eknl28fDgzMOvqadsP/vy5+Ti2dfWzrCmpFfqxo7R0+pFAAAJw0lEQVRYw+ySV0xTYRzFFdE6MO6Bmrh33HtEjUnrpQiVirRqV6q1aTqwVZJK6HJQrAVXYittSQel1XRAR+ymUoF0aiwbgpDIEEWCIb4YEy8YE9zj2fN0X87vnnP+35j/+o3GjugfrQnb123ZuADUxo1b1m1PGPt39oR1W6SNjdIFKlcoGBz+2rN17Z8zErYf0ukY/FJQKpdJqgoukDaqDIY9ayf9EWLsyq16h0UuF+gEXS6XwWUyGYxul9kdczftXjvp9/7pa3Z7fPaOjvZ2uUAVDAYZDE/UrS2jiRPLY2733rm/C7FqWSTqZTAEer1db7F4TSa9XMAYaIrQaLTLqU1u8d41Cb/0T9jgNnj0DD5P1tZhd7TrLR65nCG321vC4ptn7nfTirKLlv2qxlyI2BD0yks1PLzM5nB4LRaHz2LxDLTsaAmnnmFlni26lXZu0ZSf/x9iVklL+fjPgEDngC8Q8Fl89h5JYm9YrU1Jv1uReOsoYfb0n/WnzzA3SjV8eTueh2/r6Ot45fUyBN6hzsEWtdooEUOsheCWmQTMgXE/3j9ZMcOkkmp4rXwer9XWZ7PrBQJBF2NAon57JY00w9xMpxfSaBVZ0MVzfghY1syC0MwaDZ8v0/NaZTJbR5uAz+hyhdWX4DhmUomCTi+5XVh28xYCs2vCD/zTFEQSpNmk4evwch2Px5f12QSlDJ9HnVpIzMBlMSuZZHLGuaLilDRMFm7R98eckpycSZeqTOCGeFkrvlXWNuxvD/SmVnggGNzpDEwSLhd76vyxlHQEIjdp7neAzaRjM1Rmc0jK0+E14IY2OV7QZh/q1d4l0hXpR3FQKAUKg586cwqeDlyHpe2f9O0FdmYWNdO6mwwmPujXtMoYOq/PHug30vyVRBL84iMMDEohXLtyHA6DATnQi+vnfhuAlXLpUrHYHFIx9Hgdnt8VcvX3t3QaJXQ6kUnOQJDJMAoFei3lAgwAcnKuX7Ru+nqFSftYE7NPFovFTSGPQ4fXdUkMxnBY4ouGQICfmQFDIKAgAH4OS8kBBaQ/W7/yK8A6IgvSXPy0vFzbJBmy4dujEXEsEjFGJaFmiMJfSUYQYBQQkH6BAIwAcs/uWDvaP24rkZVMP1OcWq5Vh3scMkckFjNKjP3RqMRgBiP4/eSRBNhhwHUAAAh3ew+N7jBlH5GkuHXy8jBAPRjo+9CiNvb0FF663z3YK04sJBKJlRjECCAXyAEAGAybad00+g4TDtMhyVdOpoIVtNrEJy+fdEp6hjof52dmvr+TOPjitkLhTxLW1wPYayDguhBDuHDuzv4Jo18hseJ2Wsr5y2Xlb99qy+qQoueBvsARJYoZ6Y5lW7Ot1lg2Jo/NAbDw4QTCEkza0UeLt33pP3/evANEIrMkK4mcXMFk3iyLO0WPrz7vrHp5z5p9h5VFZpJOnGXmP0SiAWw6Flpfn19Qm4/LeHBw/vx580H/itVLligLKuPUmRw0SkRFV9+MOzkoaryqSokiFXBmotgNr5OqqRwUF11PyYULUUoRBz1TKEShl8yiLh83ZupC7qzJM/PefQRdSK6ygdtAijvZcSqyugqJJtc40Sg2t/o1G1mndKLra2uFQipXieKya+9xly5c6lw4FUywdOmS8TX+Bq4on4OsKWBTyXXO+Ltqjug1G/24Bjn+jYhb9xLJIRcg0Xk3xt/IoyIf1qKReSLkwhWrucOAT+2XW2zSYBTHpw5FVKbOqYk675dEjSYm+mSM0RZb2lJWCpQCGaEgMg0IhA2KPnAbDMcdEpY4fFoCe3ExAX0yW+bc2+aivi1LNmOyuJhFM+8Pfmg0unh98M1/0qYv/985p+33nfNt2i1q7HgcFly9d/lGS+RZR9tg153HL+4JyhG12jDSERvuann4pKONH2lRR/JdZQDwdV5p8eVb9p/af1W0pm7N7p2NIrWqM9Z274VAHRm8IRjMd6geq1XgURXOA8DDtofDqisqVcuVwUyvvPNKh69T1fbIJ7ghaAMAkMGWxsZYpNdXjqwu58Pn8+VqJO/LC0bG747kVz/ryg8/iT0Z4rvWx2KxtyxCRMux+zC4On2i3Y1qAKhbtmbz5g04RbNOSqGgSIpiSIokOf9NKSf03JoYnhl1W0dHi0Xrhw8LJRaFotFzEAzDvvUi0Q4B+Aqf1CREEEporIlhxsbG/FKp9LmUYfzvZ7LZbK6/vR3crO0Lb0sY6oUhCDoXvV+OrReINtV91jEhpdHYBzykkWTG/GMMU19gpIBiu53LjuZy/f1Wa3u7272w8O5dKYyhetk5yLV1z55Nm5d97WikGRm4lCQ9wOVnSKOdDBhJuzE+kR2dmemvAdzFfjdgvC2VtrNge4Cd25Z8uxqPJAJkvNsY8AC/xx4IIIgGSLFiYiY7k63FB7K63UXeIJFYwnAUhsXf72kHuj099fEE2dc3xlCIBvjNISeqoyY/VQDMNcA76xzPA4AsGpXpT678vquuS/TUP/X3+KXgG4RCmoAm5CQInbfwBgBybmsuB2pwuy28xWCo6qOw7NB3FYAadg144n098b6LPQEFnkEQxBxCdV4odHBiNJsFuWeLEr4E8jcYwi49LOsVL+5NTZ6khylclEoLdkrBAQDuwFohCMZfv5mYthaL09MSUH9NVUIm12YWJQBSEHu6mUJ3D0OSiFljNjtREAgAnOdfvh4qFi28gZdM1/zbWb1c6xDvrVuspuOJi4WL9cYAogk5nCim8+pb4VaCaJVdnn0zzM/NWYDbIDGcx1wyOQ4SWKy1Yipxbd26uF2jyWAo4cQIbyuM6sA/p52fHZorWSw8eAH8dpyAIWzrj8ac04cUie54ITGQNOMoihIunZdwQRfOQdr510MWS4k3ALFmHcjr0PK6H+kspkja7XaSslHmUAgldK5aS4Xg8PysxFJTKYwAv54INfx41lsG1iRHAQTFcbizVoXLW63qW8/PTwYrlcr0tIU1Yy6zJtD8s1lxzYaMrdtmSwoVjlSKxpVKmlWycvnd2ckHD4IvK5VXybRJETBu+/mkuGrD5etpjssoHBhuSqXGx8dNvdrq1ORksAZIK1y9LEfW/L8grFambUKHEsMzNJ0aT4HBhAbhg8HKVFop18rpww1Lfz0pN51gbTZaibEs5qLTNKbX3q35py5n5DI5hm9dvuR3s/rpDcIk5zApq5iSNtG0i52qBB+8EuJymVIhbv79tA7KOLY1yaXTyl6lKZ1KmYRTlZfjdlwmR8XNX8L/FtGwi8vQgMDSptT1yeD1QiHBnWxevrbuj7V2X8NRsYOlaVpoW3Grr/7Mgb3gtPJ3WrZ23/KGpqbm5oaNe1eC49J//UN9BEKHcc0j8sAbAAAAAElFTkSuQmCC';
  5 +document.getElementsByTagName('head')[0].appendChild(link);
  6 +var actual=document.URL;
  7 +var previous='';
  8 +if(actual.search('/record.php')>0||actual.search('/newzone.php')>0){
  9 + previous='zonelist.php';
  10 +}else if(actual.search('/slave_record.php')>0||actual.search('/slave_newzone.php')>0){
  11 + previous='slave_zonelist.php';
  12 +}else if(actual.search('/upload.php')>0||actual.search('/chpass.php')>0||actual.search('/options.php')>0){
  13 + previous='../';
  14 +}else if(actual.search('/convert.php')>0){
  15 + previous='upload.php';
  16 +}else if(actual.search('/user.php')>0||actual.search('/newuser.php')>0){
  17 + previous='userlist.php';
  18 +}
  19 +var md5 = function (string) {
  20 +
  21 + function RotateLeft(lValue, iShiftBits) {
  22 + return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
  23 + }
  24 +
  25 + function AddUnsigned(lX,lY) {
  26 + var lX4,lY4,lX8,lY8,lResult;
  27 + lX8 = (lX & 0x80000000);
  28 + lY8 = (lY & 0x80000000);
  29 + lX4 = (lX & 0x40000000);
  30 + lY4 = (lY & 0x40000000);
  31 + lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
  32 + if (lX4 & lY4) {
  33 + return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
  34 + }
  35 + if (lX4 | lY4) {
  36 + if (lResult & 0x40000000) {
  37 + return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
  38 + } else {
  39 + return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
  40 + }
  41 + } else {
  42 + return (lResult ^ lX8 ^ lY8);
  43 + }
  44 + }
  45 +
  46 + function F(x,y,z) { return (x & y) | ((~x) & z); }
  47 + function G(x,y,z) { return (x & z) | (y & (~z)); }
  48 + function H(x,y,z) { return (x ^ y ^ z); }
  49 + function I(x,y,z) { return (y ^ (x | (~z))); }
  50 +
  51 + function FF(a,b,c,d,x,s,ac) {
  52 + a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
  53 + return AddUnsigned(RotateLeft(a, s), b);
  54 + };
  55 +
  56 + function GG(a,b,c,d,x,s,ac) {
  57 + a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
  58 + return AddUnsigned(RotateLeft(a, s), b);
  59 + };
  60 +
  61 + function HH(a,b,c,d,x,s,ac) {
  62 + a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
  63 + return AddUnsigned(RotateLeft(a, s), b);
  64 + };
  65 +
  66 + function II(a,b,c,d,x,s,ac) {
  67 + a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
  68 + return AddUnsigned(RotateLeft(a, s), b);
  69 + };
  70 +
  71 + function ConvertToWordArray(string) {
  72 + var lWordCount;
  73 + var lMessageLength = string.length;
  74 + var lNumberOfWords_temp1=lMessageLength + 8;
  75 + var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
  76 + var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
  77 + var lWordArray=Array(lNumberOfWords-1);
  78 + var lBytePosition = 0;
  79 + var lByteCount = 0;
  80 + while ( lByteCount < lMessageLength ) {
  81 + lWordCount = (lByteCount-(lByteCount % 4))/4;
  82 + lBytePosition = (lByteCount % 4)*8;
  83 + lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
  84 + lByteCount++;
  85 + }
  86 + lWordCount = (lByteCount-(lByteCount % 4))/4;
  87 + lBytePosition = (lByteCount % 4)*8;
  88 + lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
  89 + lWordArray[lNumberOfWords-2] = lMessageLength<<3;
  90 + lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
  91 + return lWordArray;
  92 + };
  93 +
  94 + function WordToHex(lValue) {
  95 + var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
  96 + for (lCount = 0;lCount<=3;lCount++) {
  97 + lByte = (lValue>>>(lCount*8)) & 255;
  98 + WordToHexValue_temp = "0" + lByte.toString(16);
  99 + WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
  100 + }
  101 + return WordToHexValue;
  102 + };
  103 +
  104 + function Utf8Encode(string) {
  105 + string = string.replace(/\r\n/g,"\n");
  106 + var utftext = "";
  107 + for (var n = 0; n < string.length; n++) {
  108 + var c = string.charCodeAt(n);
  109 +
  110 + if (c < 128) {
  111 + utftext += String.fromCharCode(c);
  112 + }
  113 + else if((c > 127) && (c < 2048)) {
  114 + utftext += String.fromCharCode((c >> 6) | 192);
  115 + utftext += String.fromCharCode((c & 63) | 128);
  116 + }
  117 + else {
  118 + utftext += String.fromCharCode((c >> 12) | 224);
  119 + utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  120 + utftext += String.fromCharCode((c & 63) | 128);
  121 + }
  122 + }
  123 + return utftext;
  124 + };
  125 + var x=Array();
  126 + var k,AA,BB,CC,DD,a,b,c,d;
  127 + var S11=7, S12=12, S13=17, S14=22;
  128 + var S21=5, S22=9 , S23=14, S24=20;
  129 + var S31=4, S32=11, S33=16, S34=23;
  130 + var S41=6, S42=10, S43=15, S44=21;
  131 + string = Utf8Encode(string);
  132 + x = ConvertToWordArray(string);
  133 + a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
  134 + for (k=0;k<x.length;k+=16) {
  135 + AA=a; BB=b; CC=c; DD=d;
  136 + a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
  137 + d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
  138 + c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
  139 + b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
  140 + a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
  141 + d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
  142 + c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
  143 + b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
  144 + a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
  145 + d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
  146 + c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
  147 + b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
  148 + a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
  149 + d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
  150 + c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
  151 + b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
  152 + a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
  153 + d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
  154 + c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
  155 + b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
  156 + a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
  157 + d=GG(d,a,b,c,x[k+10],S22,0x2441453);
  158 + c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
  159 + b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
  160 + a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
  161 + d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
  162 + c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
  163 + b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
  164 + a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
  165 + d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
  166 + c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
  167 + b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
  168 + a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
  169 + d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
  170 + c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
  171 + b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
  172 + a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
  173 + d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
  174 + c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
  175 + b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
  176 + a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
  177 + d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
  178 + c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
  179 + b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
  180 + a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
  181 + d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
  182 + c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
  183 + b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
  184 + a=II(a,b,c,d,x[k+0], S41,0xF4292244);
  185 + d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
  186 + c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
  187 + b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
  188 + a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
  189 + d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
  190 + c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
  191 + b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
  192 + a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
  193 + d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
  194 + c=II(c,d,a,b,x[k+6], S43,0xA3014314);
  195 + b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
  196 + a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
  197 + d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
  198 + c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
  199 + b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
  200 + a=AddUnsigned(a,AA);
  201 + b=AddUnsigned(b,BB);
  202 + c=AddUnsigned(c,CC);
  203 + d=AddUnsigned(d,DD);
  204 + }
  205 + var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
  206 + return temp.toLowerCase();
  207 +}
  208 +
  209 +function passwordMD5(fromid,toid){
  210 + if (document.getElementById(fromid).value.length>0){
  211 + document.getElementById(toid).value=md5(document.getElementById(fromid).value);
  212 + }else{
  213 + document.getElementById(toid).value="#";
  214 + }
  215 +}
  216 +
  217 +function passwordChanged(fromid,toid) {
  218 + var strength = document.getElementById('pwmeter');
  219 + var hardRegex = new RegExp(/^(?=.{10,})(?=.*[A-Z].*[A-Z])(?=.*[a-z])(?=.*[0-9].*[0-9])(?=.*\W).*$/g);
  220 + var fairRegex = new RegExp(/^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\W).*$/g);
  221 + var mediRegex = new RegExp(/^(?=.{6,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$/g);
  222 + var weakRegex = new RegExp(/(?=.{4,}).*/g);
  223 + var pwd = document.getElementById(fromid);
  224 + var pwto = document.getElementById(toid);
  225 + if (pwd.value.length==0) {
  226 + strength.className='nok';
  227 + pwto.disabled=true;
  228 + } else if (false == weakRegex.test(pwd.value)) {
  229 + strength.className='bad';
  230 + pwto.disabled=true;
  231 + } else if (hardRegex.test(pwd.value)) {
  232 + strength.className='perfect';
  233 + pwto.disabled=false;
  234 + } else if (fairRegex.test(pwd.value)) {
  235 + strength.className='enough';
  236 + pwto.disabled=false;
  237 + } else if (mediRegex.test(pwd.value)) {
  238 + strength.className='almost';
  239 + pwto.disabled=true;
  240 + } else {
  241 + strength.className='notenough';
  242 + pwto.disabled=true;
  243 + }
  244 + strength.setAttribute("tag", document.getElementById(strength.className).value);
  245 + strength.setAttribute("title", document.getElementById(strength.className).value);
  246 + document.getElementById("pwc").innerHTML=document.getElementById(strength.className).value;
  247 +}
  248 +window.addEventListener('load',function(){
  249 + var tags=document.body.getElementsByTagName('*');
  250 + for(var tg=0;tg<tags.length;tg++){
  251 + var tag=tags[tg];
  252 + if(tag.id=='reload'){
  253 + (function myLoop(i){
  254 + setTimeout(function(){
  255 + --i;
  256 + document.getElementById('counter').className='attention';
  257 + document.getElementById('counter').innerHTML=i;
  258 + if(i){myLoop(i)}else{location.href='../';};
  259 + }, 1000)
  260 + })(10);
  261 + }else if(tag.id=='commitlink'){
  262 + document.getElementById('commitlink').addEventListener('click',function(){
  263 + document.getElementById('wait').style.display='block';
  264 + });
  265 + }else if(tag.id=='commitable'){
  266 + var link=document.createElement('link');
  267 + link.type='image/png';
  268 + link.rel='shortcut icon';
  269 + link.href='data:image/png;base64,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';
  270 + document.getElementsByTagName('head')[0].appendChild(link);
  271 + }else if(tag.id.search('doitlink')>0){
  272 + document.getElementById(tag.id).addEventListener('click',function(){
  273 + document.getElementById('wait').style.display='block';
  274 + });
  275 + }else if(tag.id=='choose'){
  276 + function disable(element){
  277 + document.getElementById(element).disabled=true;
  278 + document.getElementById(element+'_domain').disabled=true;
  279 + }
  280 + function enable(element){
  281 + document.getElementById(element).disabled=false;
  282 + document.getElementById(element+'_domain').disabled=false;
  283 + if(element=='sel'){
  284 + document.getElementById(element).focus();
  285 + }else{
  286 + document.getElementById(element+'_domain').focus();
  287 + }
  288 + }
  289 + document.getElementById('file').addEventListener('click',function(){
  290 + disable('txt');
  291 + disable('sel');
  292 + enable('fil');
  293 + });
  294 + document.getElementById('text').addEventListener('click',function(){
  295 + disable('fil');
  296 + disable('sel');
  297 + enable('txt');
  298 + });
  299 + document.getElementById('sel').addEventListener('change',function(){
  300 + var selvalue=document.getElementById('sel').value;
  301 + if(selvalue=='- select file -'){
  302 + selvalue='';
  303 + }
  304 + document.getElementById('sel_domain').value=selvalue;
  305 + });
  306 + document.getElementById('list').addEventListener('click',function(){
  307 + disable('fil');
  308 + disable('txt');
  309 + enable('sel');
  310 + });
  311 + disable('fil');
  312 + disable('txt');
  313 + disable('sel');
  314 + }else if(tag.id=='password'){
  315 + document.getElementById('normal').addEventListener('submit', function(){
  316 + passwordMD5('password', 'pwmd5');
  317 + });
  318 + window.addEventListener('keyup',function(keyevent){
  319 + if(!keyevent)keyevent=event;
  320 + var code=keyevent.keyCode;
  321 + if(code==13){
  322 + document.getElementById('submit').click();
  323 + }
  324 + });
  325 + }else if(tag.id=='pass1'){
  326 + document.getElementById('new').addEventListener('submit', function(){
  327 + passwordMD5('pass1', 'pwmd5n');
  328 + });
  329 + window.addEventListener('keyup',function(keyevent){
  330 + if(!keyevent)keyevent=event;
  331 + var code=keyevent.keyCode;
  332 + if(code==13){
  333 + document.getElementById('submit').click();
  334 + }
  335 + passwordChanged('pass1','pass2');
  336 + });
  337 + }else if(tag.id=='pass_o'){
  338 + document.getElementById('chg').addEventListener('submit', function(){
  339 + passwordMD5('pass_n1', 'pwmd5n');
  340 + passwordMD5('pass_o', 'pwmd5');
  341 + });
  342 + window.addEventListener('keyup',function(keyevent){
  343 + if(!keyevent)keyevent=event;
  344 + var code=keyevent.keyCode;
  345 + if(code==13){
  346 + document.getElementById('submit').click();
  347 + }
  348 + passwordChanged('pass_n1','pass_n2');
  349 + });
  350 + }else if(tag.id=='pass2'){
  351 + window.addEventListener('keyup',function(keyevent){
  352 + if(!keyevent)keyevent=event;
  353 + var code=keyevent.keyCode;
  354 + if(code==13){
  355 + document.getElementById('submit').click();
  356 + }
  357 + alfa=document.getElementById('pass1').value;
  358 + beta=document.getElementById('pass2').value;
  359 + need=document.getElementById('notempty').value;
  360 + if(alfa==beta&&(need=='0'||beta.length>0)){
  361 + document.getElementById('submit').disabled=false;
  362 + }else{
  363 + document.getElementById('submit').disabled=true;
  364 + }
  365 + });
  366 + }else if(tag.id=='pass_n2'){
  367 + window.addEventListener('keyup',function(keyevent){
  368 + if(!keyevent)keyevent=event;
  369 + var code=keyevent.keyCode;
  370 + if(code==13){
  371 + document.getElementById('submit').click();
  372 + }
  373 + alfa=document.getElementById('pass_n1').value;
  374 + beta=document.getElementById('pass_n2').value;
  375 + if(alfa==beta&&beta.length>0){
  376 + document.getElementById('submit').disabled=false;
  377 + }else{
  378 + document.getElementById('submit').disabled=true;
  379 + }
  380 + });
  381 + }else if(tag.id=='nofile'){
  382 + document.getElementById('list').disabled=true;
  383 + }else if(tag.id=='close'){
  384 + document.getElementById('close').addEventListener('click',function(){
  385 + document.getElementById('errorbox').style.display='none';
  386 + document.getElementById('errshadow').style.display='none';
  387 + });
  388 + }else if(tag.id=='cancel'){
  389 + window.addEventListener('keyup',function(keyevent){
  390 + if(!keyevent)keyevent=event;
  391 + var code=keyevent.keyCode;
  392 + if(code==27){
  393 + document.getElementById('cancel').click();
  394 + }
  395 + });
  396 + document.getElementById('cancel').addEventListener('click',function(){
  397 + location.href=previous;
  398 + });
  399 + }else if(tag.id=='prev'){
  400 + window.addEventListener('keyup',function(keyevent){
  401 + if(!keyevent)keyevent=event;
  402 + var code=keyevent.keyCode;
  403 + if(code==37&keyevent.ctrlKey){
  404 + document.getElementById('prev').click();
  405 + }
  406 + });
  407 + }else if(tag.id=='next'){
  408 + window.addEventListener('keyup',function(keyevent){
  409 + if(!keyevent)keyevent=event;
  410 + var code=keyevent.keyCode;
  411 + if(code==39&keyevent.ctrlKey){
  412 + document.getElementById('next').click();
  413 + }
  414 + });
  415 + }else if(tag.id=='first'){
  416 + window.addEventListener('keyup',function(keyevent){
  417 + if(!keyevent)keyevent=event;
  418 + var code=keyevent.keyCode;
  419 + if(code==38&keyevent.ctrlKey){
  420 + document.getElementById('first').click();
  421 + }
  422 + });
  423 + }else if(tag.id=='last'){
  424 + window.addEventListener('keyup',function(keyevent){
  425 + if(!keyevent)keyevent=event;
  426 + var code=keyevent.keyCode;
  427 + if(code==40&keyevent.ctrlKey){
  428 + document.getElementById('last').click();
  429 + }
  430 + });
  431 + }else if(tag.id=='new'){
  432 + window.addEventListener('keyup',function(keyevent){
  433 + if(!keyevent)keyevent=event;
  434 + var code=keyevent.keyCode;
  435 + if(code==45){
  436 + document.getElementById('new').click();
  437 + }
  438 + });
  439 + }
  440 + }
  441 +});
  442 +var RecaptchaOptions={theme:'white'};
... ...
templates/accessdenied.tpl 0 → 100644
  1 +<div class=clear><div class=main><p>
  2 +<h4>A general error has occurred.</h4>
  3 +<strong>Reason:</strong>
  4 +{if $reason}{$reason}
  5 +{else}Perhaps you are trying to view a page that you are not allowed to view, or that one of the filters has detected an injection attack. If you are seeing this message, there's a good chance we haven't written a decent error message yet.
  6 +{/if}
  7 +</p></div></div>
... ...
templates/chpass.tpl 0 → 100644
  1 +<div class=clear><div class=main><h4>Edit your password:</h4>
  2 +<table width=580>
  3 +<tr>
  4 +<td width=120 align=right>Old password:</td>
  5 +<td>
  6 +<input class=form-field type=password name=password_oldx id=pass_o tabindex=1 autofocus></td>
  7 +<th width=180>Password quality meter<div class=pwc id=pwc>Cannot be empty!</div></th>
  8 +</tr>
  9 +<tr>
  10 +<td width=120 align=right>New password:</td>
  11 +<td><input class=form-field type=password name=pass1 id=pass_n1 tabindex=2 ></td>
  12 +<td rowspan=2 id=pwmeter class=nok width=180 title="Cannot be empty!" alt="Cannot be empty!"></tr>
  13 +<tr>
  14 +<td width=120 align=right>Confirm it:</td>
  15 +<td><input class=form-field type=password name=pass2 id=pass_n2 tabindex=3 disabled></td>
  16 +</tr>
  17 +</table>
  18 +<form name=chg id=chg method="post" action="{$src}savepass.php"><input type=hidden id=pwmd5 name=password_old><input type=hidden id=pwmd5n name=password_one>
  19 +<div class=submit><input class=submit-button type=submit name=Submit value="Save" id=submit tabindex=4 disabled>&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel"></div>
  20 +</form>
  21 +<input type=hidden name=bad id=bad value="The password is too short">
  22 +<input type=hidden name=nok id=nok value="Cannot be empty!">
  23 +<input type=hidden name=notenough id=notenough value="Need to be longer!">
  24 +<input type=hidden name=almost id=almost value="Need to be complex and/or longer!">
  25 +<input type=hidden name=enough id=enough value="Complexity is fair">
  26 +<input type=hidden name=perfect id=perfect value="Complexity is perfect">
  27 +</div></div>
... ...
templates/commit.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +<h4>Commit changes to the system</h4>
  3 +<p>Are you sure to commit all validated changes to the system?</p>
  4 +<p><a class=attention id=commitlink href="?commit=y">Yes</a> - <a href="{$base}">No</a></p>
  5 +</div></div>
... ...
templates/commitdone.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +<h4>Commit report</h4>
  3 +{if $success}<p>The following procedures have been done:</p><pre>{$success}</pre>{else}<p>No successed process.</p>{/if}
  4 +</div></div>
... ...
templates/deleteuser.tpl 0 → 100644
  1 +<div class=clear><div class=main><p>Please confirm that you wish to delete the user <strong>{$user.realname} ({$user.username}).</strong></p>
  2 +<p>
  3 +Any current zone ownership will reset to the main admin user.
  4 +</p>
  5 +<p>
  6 +<a class=attention href="{$src}userlist.php?i={$user.id}&amp;delete=y">Yes</a> - <a href="{$src}userlist.php">No</a>.
  7 +</p></div></div>
... ...
templates/deletezone.tpl 0 → 100644
  1 +<div class=clear><div class=main><p>Please confirm that you wish to delete the master zone <strong>{$zone}.</strong></p>
  2 +<p><br />
  3 +All resource records associated with this zone will be deleted.
  4 +</p><p><a class=attention href="{$src}zonelist.php?i={$zoneid}&amp;delete=y">Yes</a> - <a href="{$src}zonelist.php">No</a>.
  5 +</p></div></div>
... ...
templates/footer.tpl 0 → 100644
  1 +<div class=footer>{$footerleft}<span class=copy>{$footerright}</span></div>
  2 +<div class=shadow id=wait></div>{if $popuperror}<div class=errshadow id=errshadow></div><div class=errorbox id=errorbox><p><strong>Error:</strong></p><p>{$popuperror}</p><table align=center><tr><td class=close id=close>Ok</td></tr></table><p></p></div>{/if}
  3 +</body>
  4 +</html>
... ...
templates/header.tpl 0 → 100644
  1 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  2 +<html>
  3 +<head>
  4 +<title>{$TITLE} - {$pagetitle}</title>
  5 +<meta http-equiv="Content-Language" content="en">
  6 +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7 +<link rel="stylesheet" type=text/css href="{if $sdomain}//{$sdomain}{/if}{$static}{$skin}.css" />
  8 +<script src="{if $sdomain}//{$sdomain}{/if}{$static}{$skin}.js"></script>
  9 +</head>
0 10 \ No newline at end of file
... ...
templates/login.tpl 0 → 100644
  1 +<div class=login><div class=loginform>
  2 +<h4>Enter your credentials:</h4>
  3 +<form method="post" name=login action="{if $action}{$action}{/if}" id=normal>
  4 +<table align=center width=400>
  5 +<tr>
  6 +<td align=right>Username:</td>
  7 +<td align=right><input class=form-field type=text name=username autofocus tabindex=1></td>
  8 +</tr>
  9 +</table>
  10 +<div class=loginend>
  11 +<table align=center width=400>
  12 +{if $recaptcha != "" }
  13 +<tr>
  14 +<td colspan=2><label for="recaptcha">Fill the captcha:</label></td>
  15 +</tr>
  16 +<tr>
  17 +<td align=center colspan=2 id=captchaload>{nocache}{$recaptcha}{/nocache}</td>
  18 +</tr>
  19 +{else}
  20 +<tr>
  21 +<td colspan=2><span class=whitelist>You're allowed without captcha:</span></td>
  22 +</tr>
  23 +<tr>
  24 +<td colspan=2 class=nocap><span class=disablestamp>don't need</span></td>
  25 +</tr>
  26 +{/if}
  27 +<tr>
  28 +<td colspan=2><hr /></td>
  29 +</tr>
  30 +<tr>
  31 +<td colspan=2 align=center><input type=hidden name=password id=pwmd5><input class=submit-button type=submit name=Submit value="Login" id=submit tabindex=3></td>
  32 +</tr>
  33 +</table></div></form>
  34 +<table align=center width=400>
  35 +<tr>
  36 +<td align=right>Password:</td>
  37 +<td align=right><input class=form-field type=password name=password_local id=password tabindex=2></td>
  38 +</tr>
  39 +</table>
  40 +</div>
  41 +</div>
... ...
templates/logout.tpl 0 → 100644
templates/main.tpl 0 → 100644
  1 +{include file="header.tpl"}<body>
  2 +<div class=title>{$TITLE}</div>
  3 +<div class=section><p>{$pagetitle}</p></div>{include file="menu.tpl"}{include file=$template}
  4 +<div class=hint><p>{$help}</p></div>
  5 +{if $loggedinuser}<div class=loggeduser>Logged in as: <strong>{$loggedinuser}</strong></div>{/if}{include file="footer.tpl"}
... ...
templates/mainpage.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +<p><strong>Welcome, {$user}.</strong>
  3 +{if $admin == "yes"} (You have administrator privileges){/if}</p>
  4 +{if $status == 0}DNS Service is <b>running</b>.{/if}
  5 +{if $status == 1}DNS Service is <b><span class=attention>stopped</span></b>.{/if}
  6 +<p>You maintain <strong>{$zones}</strong> master zone{if $zones > 1}s{/if} and <strong>{$slave_zones}</strong> slave zone{if $slave_zones > 1}s{/if}.</p>
  7 +{if $bad || $bad_slaves}<h4>Zones need to be check or modify</h4><p>{if $bad}Master: {section name=i loop=$bad}<a class=attention href="{$src}record.php?i={$bad[i].id}"><b>{$bad[i].name}</b></a>&nbsp;&nbsp;&nbsp;{/section}<br />{/if}
  8 +{if $bad_slaves}Slave: {section name=i loop=$bad_slaves}<a class=attention href="{$src}slave_record.php?i={$bad_slaves[i].id}"><b>{$bad_slaves[i].name}</b></a>&nbsp;&nbsp;&nbsp;{/section}{/if}</p>{/if}
  9 +{if $comm || $comm_slaves}<h4>Zones need to be commit</h4><p>{if $comm}Master: {section name=i loop=$comm}<a class=attention href="{$src}record.php?i={$comm[i].id}"><b>{$comm[i].name}</b></a>&nbsp;&nbsp;&nbsp;{/section}<br />{/if}
  10 +{if $comm_slaves}Slave: {section name=i loop=$comm_slaves}<a class=attention href="{$src}slave_record.php?i={$comm_slaves[i].id}"><b>{$comm_slaves[i].name}</b></a>&nbsp;&nbsp;&nbsp;{/section}{/if}</p>{/if}
  11 +{if $del || $del_slaves}<h4>Zones mark as deleted</h4><p>{if $del}Master: {section name=i loop=$del}<span class=deleted><span class=attention><b>{$del[i].name}</b></span></span>&nbsp;&nbsp;&nbsp;{/section}<br />{/if}
  12 +{if $del_slaves}Slave: {section name=i loop=$del_slaves}<span class=deleted><span class=attention><b>{$del_slaves[i].name}</b></span></span>&nbsp;&nbsp;&nbsp;{/section}{/if}</p>{/if}
  13 +</div></div>
... ...
templates/menu.tpl 0 → 100644
  1 +{if $menu_button}<div class=menu>
  2 +<p class=tag>Menu</p>
  3 +{section name=i loop=$menu_button}
  4 +{if $menu_button[i].title == "Commit changes"}
  5 +{if $donotcommit == "yes"}<span class=disabled>{$menu_button[i].title}<br /></span>
  6 +{else}<a href="{$menu_button[i].link}">{$menu_button[i].title}</a><br />
  7 +{/if}
  8 +{elseif $menu_button[i].link != $menu_current}<a href="{$menu_button[i].link}">{$menu_button[i].title}</a><br />
  9 +{else}<span class=currmenu>{$menu_button[i].title}</span><br />
  10 +{/if}
  11 +{/section}
  12 +</div>
  13 +{/if}
0 14 \ No newline at end of file
... ...
templates/newuser.tpl 0 → 100644
  1 +<div class=clear><div class=main><form name=form1 method="post" action="{$src}userlist.php" id=new>
  2 +<h4>Properties of the new user:</h4><div class=submit>
  3 +<input class=submit-button type=submit name=Submit value="Save" disabled id=submit tabindex=6>&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel" tabindex=8></div>
  4 +<table width=580>
  5 +<tr>
  6 +<td align=right width=120><strong>Username:</strong></td>
  7 +<td><input type=text name=username_ class=form-field autofocus tabindex=1></td>
  8 +</tr>
  9 +<tr>
  10 +<td align=right width=120><strong>Full name:</strong></td>
  11 +<td><input type=text name=realname class=form-field tabindex=2></td>
  12 +</tr>
  13 +<tr>
  14 +<td align=right width=120><strong>Admin rights:</strong></td>
  15 +<td height="30">
  16 +<input type=radio name=admin id=adminy value="yes" tabindex=3 /><label for="adminy">yes</label>
  17 +<input type=radio name=admin id=adminn value="no" checked="checked" tabindex=3 /><label for="adminn">no</label>
  18 +<input type=hidden name=password_ id=pwmd5n>
  19 +</td>
  20 +</tr>
  21 +</table></form>
  22 +<table width=580>
  23 +<tr>
  24 +<td align=right width=120><strong>Password:</strong></td>
  25 +<td><input type=password name=password_one class=form-field id=pass1 tabindex=4></td>
  26 +<th width=180>Password quality meter<div class=pwc id=pwc>Cannot be empty!</div></th>
  27 +</tr>
  28 +<tr>
  29 +<td align=right width=120><strong>Confirm it:</strong></td>
  30 +<td><input type=password name=confirm_password class=form-field id=pass2 disabled tabindex=5></td>
  31 +<td rowspan=2 id=pwmeter class=nok width=180 title="Cannot be empty!" alt="Cannot be empty!">
  32 +<input type=hidden name=bad id=bad value="The password is too short">
  33 +<input type=hidden name=nok id=nok value="Cannot be empty!">
  34 +<input type=hidden name=notenough id=notenough value="Need to be longer!">
  35 +<input type=hidden name=almost id=almost value="Need to be complex and/or longer!">
  36 +<input type=hidden name=enough id=enough value="Complexity is fair">
  37 +<input type=hidden name=perfect id=perfect value="Complexity is perfect">
  38 +<input type=hidden name=notempty id=notempty value=1>
  39 +</td>
  40 +</tr>
  41 +<tr>
  42 +<td colspan=2 height=30></td>
  43 +</tr>
  44 +</table>
  45 +</div></div>
... ...
templates/newzone.tpl 0 → 100644
  1 +<form name=form1 method="post" action="{$src}zonelist.php">
  2 +<div class=clear><div class=main><h4>Properties of the new master zone:</h4>
  3 +<table>
  4 +<tr>
  5 +<td align=right><strong>Zone:</strong></td>
  6 +<td><input type=text name=name class=form-field autofocus></td>
  7 +</tr>
  8 +<tr>
  9 +<td align=right><strong>Refresh:</strong></td>
  10 +<td><input type=text name=refresh class=form-field value="86400"></td>
  11 +</tr>
  12 +<tr>
  13 +<td align=right><strong>Retry:</strong></td>
  14 +<td><input type=text name=retry class=form-field value="7200"></td>
  15 +</tr>
  16 +<tr>
  17 +<td align=right><strong>Expire:</strong></td>
  18 +<td><input type=text name=expire class=form-field value="3600000"></td>
  19 +</tr>
  20 +<tr>
  21 +<td align=right><strong>Time To Live:</strong></td>
  22 +<td><input type=text name=ttl class=form-field value="300"></td>
  23 +</tr>
  24 +<tr>
  25 +<td align=right><strong>Primary NS:</strong></td>
  26 +<td><input type=text name=pri_dns class=form-field value="{$pri_dns}"></td>
  27 +</tr>
  28 +<tr>
  29 +<td align=right><strong>Secondary NS:</strong></td>
  30 +<td><input type=text name=sec_dns class=form-field value="{$sec_dns}"></td>
  31 +</tr>
  32 +<tr>
  33 +<td align=right><strong>Web Server:</strong></td>
  34 +<td><input type=text name=www class=form-field value=""></td>
  35 +</tr>
  36 +<tr>
  37 +<td align=right><strong>Mail Server:</strong></td>
  38 +<td><input type=text name=mail class=form-field value=""></td>
  39 +</tr>
  40 +<tr>
  41 +<td align=right><strong>FTP Server:</strong></td>
  42 +<td><input type=text name=ftp class=form-field value=""></td>
  43 +</tr>
  44 +<tr>
  45 +<td colspan=2><hr /></td>
  46 +</tr>
  47 +<tr>
  48 +<td align=right><strong>Owner: </strong></td>
  49 +<td><select name=owner class=form-field>
  50 +{section name=i loop=$userlist}
  51 +<option value="{$userlist[i].id}" {if $current_user == $userlist[i].id}selected{/if}>{$userlist[i].realname}</option>
  52 +{/section}
  53 +</select>
  54 +</td>
  55 +</tr>
  56 +</table></div></div>
  57 +<div class=submit><input class=submit-button type=submit name=Submit value="Add zone">&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel"></div>
  58 +</form>
... ...
templates/optionsread.tpl 0 → 100644
  1 +<form name=form1 method="post" action="{$src}options.php">
  2 +<div class=clear><div class=main>
  3 +<h4>Record Types</h4>
  4 +<table style="min-width:600">
  5 +{section name=x loop=$records}
  6 +<tr>
  7 +{section name=y loop=$records[x]}
  8 +<td>
  9 +<input type=checkbox id={$records[x][y].prefkey} name={$records[x][y].prefkey} {if $records[x][y].prefval == "on"}checked{/if} />
  10 +<label for="{$records[x][y].prefkey}" name={$records[x][y].prefkey}_lbl>{$records[x][y].prefkey}</label>
  11 +</td>
  12 +{/section}
  13 +</tr>
  14 +{/section}
  15 +</table>
  16 +<table>
  17 +<tr><td colspan=2><hr /></td></tr>
  18 +{section name=prefkey loop=$options}
  19 +<tr>
  20 +<td align=right>
  21 +{if $options[prefkey].prefkey == "hostmaster"}Site Hostmaster Address:{/if}
  22 +{if $options[prefkey].prefkey == "range"}Items Per Page:{/if}
  23 +{if $options[prefkey].prefkey == "prins"}Default Primary NS:{/if}
  24 +{if $options[prefkey].prefkey == "secns"}Default Secondary NS:{/if}
  25 +{if $options[prefkey].prefkey == "master"}Default master for slaves:{/if}
  26 +</td>
  27 +<td><input class=form-field type=text size="35" name={$options[prefkey].prefkey} value="{$options[prefkey].prefval}" {if $options[prefkey].prefkey == "hostmaster"}autofocus{/if}></td>
  28 +</tr>
  29 +{/section}
  30 +</table>
  31 +</div></div>
  32 +<div class=submit><input class=submit-button type=submit name=Submit value="Save">&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel"></div>
  33 +</form>
... ...
templates/pages.tpl 0 → 100644
  1 +{if $pages}
  2 +<div class=pages>
  3 +<table>
  4 +<tr>
  5 +<td class=pages>Paging:</td>
  6 +{foreach name=pages from=$pages item=page}
  7 +{if $smarty.foreach.pages.first}
  8 +{if $current_page == $page}
  9 +<td class=firstno>&nbsp;</td>
  10 +<td class=prevno>&nbsp;</td>
  11 +{else}
  12 +<td class=first><a class=first id=first href="{$page_root}page={$page}" alt="First page" title="First page">&nbsp;</a></td>
  13 +<td class=prev><a class=prev id=prev href="{$page_root}page={math equation="$current_page - 1"}" alt="Previous page" title="Previous page">&nbsp;</a></td>
  14 +{/if}
  15 +{/if}
  16 +{if $current_page == $page}
  17 +<td class="pages actualpage">{$page}</td>
  18 +{else}
  19 +<td class=pages><a href="{$page_root}page={$page}" alt="Go to {$page} page" title="Go to {$page}. page">{$page}</a></td>
  20 +{/if}
  21 +{if $smarty.foreach.pages.last}
  22 +{if $current_page == $page}
  23 +<td class=nextno>&nbsp;</td>
  24 +<td class=lastno>&nbsp;</td>
  25 +{else}
  26 +<td class=next><a class=next id=next href="{$page_root}page={math equation="$current_page + 1"}" alt="Next page" title="Next page">&nbsp;</a></td>
  27 +<td class=last><a class=last id=last href="{$page_root}page={$page}" alt="Last page" title="Last page">&nbsp;</a></td>
  28 +{/if}
  29 +{/if}
  30 +{/foreach}
  31 +</tr>
  32 +</table>
  33 +</div>
  34 +{/if}
... ...
templates/recordread.tpl 0 → 100644
  1 +<form name=form1 method="post" action="{$src}record.php?i={$zone.id}">
  2 +<div class=clear><div class=main>
  3 +<h4>Edit zone records</h4>
  4 +<table style="min-width:820">
  5 +<tr>
  6 +<td><strong>New:</strong></td>
  7 +<td><input type=text name=newhost class=form-field size="16" autofocus></td>
  8 +<td><input type=text name=newttl class=form-field size="1"></td>
  9 +<td><select name=newtype class=form-field>
  10 +{html_options values=$types output=$types}
  11 +</select></td>
  12 +<td><input type=text name=newdestination class=form-field size="32"></td>
  13 +</tr>
  14 +<tr>
  15 +<td colspan=5><hr /></td>
  16 +</tr>
  17 +</table>
  18 +<table style="min-width:820">
  19 +<tr>
  20 +<td align=right><strong>Zone:</strong></td>
  21 +<td class=highlight>{$zone.name}</td>
  22 +<td align=right><strong>Serial:</strong></td>
  23 +<td>{$zone.serial}</td>
  24 +</tr>
  25 +<tr>
  26 +<td align=right><strong>Refresh:</strong></td>
  27 +<td><input type=text name=refresh size="28" class=form-field value="{$zone.refresh}"></td>
  28 +<td align=right><strong>Retry:</strong></td>
  29 +<td><input type=text name=retry size="28" class=form-field value="{$zone.retry}"></td>
  30 +</tr>
  31 +<tr>
  32 +<td align=right><strong>Expire:</strong></td>
  33 +<td><input type=text name=expire size="28" class=form-field value="{$zone.expire}"></td>
  34 +<td align=right><strong>TTL:</strong></td>
  35 +<td><input type=text name=ttl size="28" class=form-field value="{$zone.ttl}"></td>
  36 +</tr>
  37 +<tr>
  38 +<td align=right><strong>NS1:</strong></td>
  39 +<td><input type=text name=pri_dns size="28" class=form-field value="{$zone.pri_dns}"></td>
  40 +<td align=right><strong>NS2:</strong></td>
  41 +<td><input type=text name=sec_dns size="28" class=form-field value="{$zone.sec_dns}"></td>
  42 +</tr>
  43 +{if $admin == "yes"}
  44 +<tr>
  45 +<td align=right><strong>Owner:</strong></td>
  46 +<td align=left><select name=owner class=form-field>
  47 +{section name=i loop=$userlist}
  48 +<option value="{$userlist[i].id}"{if $userlist[i].id == $zone.owner} selected{/if}>{$userlist[i].realname}</option>
  49 +{/section}
  50 +</select>
  51 +</td>
  52 +<td align=right><strong>Secure:</strong></td>
  53 +<td align=left><select name=secured class=form-field>
  54 +<option value="yes"{if $zone.secured == "yes"} selected{/if}>yes</option>
  55 +<option value="no"{if $zone.secured == "no"} selected{/if}>no</option>
  56 +</select>
  57 +</td>
  58 +</tr>
  59 +{/if}
  60 +</table>
  61 +<input type=hidden name=zone value="{$zone.name}">
  62 +<input type=hidden name=zoneid value="{$zone.id}">
  63 +{if $rcount > 0}
  64 +<table style="min-width:780">
  65 +<tr>
  66 +<th>Host</th>
  67 +<th>TTL</th>
  68 +<th>Type</th>
  69 +<th colspan=2>Destination</th>
  70 +<th>Delete</th>
  71 +</tr>
  72 +{section name=i loop=$record}
  73 +<tr>
  74 +<td>
  75 +<input type=text name=host[{$smarty.section.i.index}] class=form-field value="{$record[i].host}" size="16">
  76 +<input type=hidden name=host_id[{$smarty.section.i.index}] value="{$record[i].id}">
  77 +</td>
  78 +<td>
  79 +<input type=text name=rttl[{$smarty.section.i.index}] class=form-field value="{$record[i].ttl}" size="1">
  80 +</td>
  81 +<td><select name=type[{$smarty.section.i.index}] class=form-field>
  82 +{html_options values=$types selected=$record[i].type output=$types}
  83 +</select></td>
  84 +{if $record[i].type == "MX"}
  85 +<td>
  86 +<input type=text name=pri[{$smarty.section.i.index}] class=form-field size="1" maxlength="3" value="{$record[i].pri}">
  87 +</td><td>
  88 +<input type=text name=destination[{$smarty.section.i.index}] class=form-field size="25" value="{$record[i].destination}">
  89 +</td>
  90 +{else}
  91 +<td colspan=2>
  92 +<input type=text name=destination[{$smarty.section.i.index}] class=form-field size="33" value="{$record[i].destination}">
  93 +</td>
  94 +{/if}
  95 +<td align=center><input type=checkbox name=delete[{$smarty.section.i.index}] id=delete[{$smarty.section.i.index}]><label for="delete[{$smarty.section.i.index}]" name=delete[{$smarty.section.i.index}]_lbl>&nbsp;</label></td>
  96 +</tr>
  97 +{/section}
  98 +</table>{else}<p>There are no other records in this zone at the moment.</p>{/if}
  99 +<input type=hidden name=total value="{$smarty.section.i.total}">
  100 +</div></div>
  101 +<div class=submit><input class=submit-button type=submit name=Submit value="Save">&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel"></div>
  102 +</form>
  103 +{include file="pages.tpl"}
... ...
templates/savepass.tpl 0 → 100644
  1 +<div class=clear><div class=main><p>
  2 +Your password was successfully changed.</p><p>Your new password is applied immediately, so you don't need to relogin.</p></div></div>
... ...
templates/slave_deletezone.tpl 0 → 100644
  1 +<div class=clear><div class=main><p>Please confirm that you wish to delete the slave zone <strong>{$zone}.</strong></p>
  2 +<p><br />
  3 +All resource records associated with this zone will be deleted.
  4 +</p>
  5 +<p>
  6 +<a class=attention href="{$src}slave_zonelist.php?i={$zoneid}&amp;delete=y">Yes</a> - <a href="{$src}slave_zonelist.php">No</a>.
  7 +</p></div></div>
... ...
templates/slave_newzone.tpl 0 → 100644
  1 +<form name=form1 method="post" action="{$src}slave_zonelist.php">
  2 +<div class=clear><div class=main><h4>Properties of the new slave zone:</h4>
  3 +<table>
  4 +<tr>
  5 +<td align=right><strong>Zone:</strong></td>
  6 +<td><input type=text name=name class=form-field autofocus></td>
  7 +</tr>
  8 +<tr>
  9 +<td align=right><strong>Master:</strong></td>
  10 +<td><input type=text name=master class=form-field value="{$master}"></td>
  11 +</tr>
  12 +<tr>
  13 +<td colspan=2><hr /></td>
  14 +</tr>
  15 +<tr>
  16 +<td align=right><strong>Owner: </strong></td>
  17 +<td><select name=owner class=form-field>
  18 +{section name=i loop=$userlist}
  19 +<option value="{$userlist[i].id}" {if $current_user == $userlist[i].id}selected{/if}>{$userlist[i].realname}</option>
  20 +{/section}
  21 +</select>
  22 +</td>
  23 +</tr>
  24 +</table></div></div>
  25 +<div class=submit><input class=submit-button type=submit name=Submit value="Add zone">&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel"></div>
  26 +</form>
... ...
templates/slave_recordread.tpl 0 → 100644
  1 +<form name=form1 method="post" action="{$src}slave_zonelist.php?i={$zone.id}">
  2 +<div class=clear><div class=main><h4>Edit properties of the slave zone:</h4>
  3 +<table>
  4 +<tr>
  5 +<td align=right><strong>Zone:</strong></td>
  6 +<td class=highlight>{$zone.name}</td>
  7 +</tr>
  8 +<tr>
  9 +<td align=right><strong>Master:</strong></td>
  10 +<td><input type=text name=master size="25" class=form-field value="{$zone.master}"></td>
  11 +</tr>
  12 +{if $admin == "yes"}
  13 +<tr>
  14 +<td align=right><strong>Owner:</strong></td>
  15 +<td align=left><select name=owner class=form-field>
  16 +{section name=i loop=$userlist}
  17 +<option value="{$userlist[i].id}"{if $userlist[i].id == $zone.owner} selected{/if}>{$userlist[i].realname}</option>
  18 +{/section}
  19 +</select>
  20 +</td>
  21 +</tr>
  22 +{/if}
  23 +</table>
  24 +<input type=hidden name=name value="{$zone.name}">
  25 +</div></div>
  26 +<div class=submit><input class=submit-button type=submit name=Submit value="Save">&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel"></div>
  27 +</form>
... ...
templates/slave_zoneread.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +{if $admin == 'yes'}<p><a class=new id=new href="{$src}slave_newzone.php">Create a new slave zone</a></p>{else}<h4>List of your slave zones</h4>{/if}
  3 +{if $zonelist}<table style="min-width:500">
  4 +<tr>
  5 +<th>Name</th>
  6 +<th>Master</th>
  7 +<th>Changed</th>
  8 +<th>&nbsp;</th>
  9 +<th colspan=2>Valid</th>
  10 +<th>&nbsp;</th>
  11 +<th colspan=2>Action</th>
  12 +</tr>
  13 +{section name=i loop=$zonelist}
  14 +<tr>
  15 +<td>{$zonelist[i].name}</td>
  16 +<td>{$zonelist[i].master}</td>
  17 +
  18 +{if $zonelist[i].updated == "yes"}<td class=ok title=Yes alt=Yes>&nbsp;</td>
  19 +{elseif $zonelist[i].updated == "no"}<td class=no title=No alt=No>&nbsp;</td>
  20 +{else}<td class=some title=Unknown alt=Unknown></td>
  21 +{/if}
  22 +<td class=empty>&nbsp;</td>
  23 +{if $zonelist[i].valid == "yes"}{if $zonelist[i].updated == "no"}<td class=ok title=Yes alt=Yes>&nbsp;</td><td class=view><a alt="View slave zone" title="View slave zone" href="{$src}slave_zoneview.php?i={$zonelist[i].id}">&nbsp;</a></td>{else}<td class=ok title=Yes alt=Yes>&nbsp;</td><td class=preview><a alt="preview zone" title="Preview zone" href="{$src}slave_zoneview.php?i={$zonelist[i].id}&pre=y">&nbsp;</a></td>{/if}
  24 +{elseif $zonelist[i].valid == "no"}<td class=nok title=No alt=No></td><td class=empty></td>
  25 +{else}<td class=some title=Maybe alt=Maybe></td><td class=check><a id=_doitlink_{$zonelist[i].id} alt="Check zone" title="Check zone" href="{$src}slave_zonelist.php?i={$zonelist[i].id}&check=y{if $pages}&page={$current_page}{/if}">&nbsp;</a></td>
  26 +{/if}
  27 +<td class=empty>&nbsp;</td>
  28 +<td class=ed><a title="Edit zone" alt="Edit zone" href="{$src}slave_record.php?i={$zonelist[i].id}">&nbsp;</a></td>
  29 +<td class=del><a alt="Remove zone" title="Remove zone" href="{$src}slave_deletezone.php?i={$zonelist[i].id}">&nbsp;</a></td>
  30 +</tr>
  31 +{/section}
  32 +</table>{else}<p>You don't have slave zones.</p>{/if}
  33 +</div></div>
  34 +{include file="pages.tpl"}
... ...
templates/upload.tpl 0 → 100644
  1 +<form name=upl enctype=multipart/form-data action="{$src}convert.php" method="post">
  2 +<div class=clear><div class=main>
  3 +<h4 id=choose>Import a zone file</h4>
  4 +<p{if $count == 0} id=nofile{/if}>Choose an import method, a file/zone (don't forget to fill the domain part).</p>
  5 +<table>
  6 +<tr>
  7 +<td><input type=radio name=method id=list value="list"><label for="list">Orphan files</label></td>
  8 +<td class=empty>
  9 +<td><select class=form-field id=sel name=sel>
  10 +{if $count == 0}<option> NOT FOUND </option>{else}<option>- select file -</option>{/if}
  11 +{section name=i loop=$files}
  12 +<option>{$files[i]}</option>
  13 +{/section}
  14 +</select>&nbsp;<strong>Domain:&nbsp;</strong><input class=form-field id=sel_domain value="" name=sel_domain></td>
  15 +</tr>
  16 +<tr>
  17 +<td><input type=radio name=method id=file value="file"><label for="file">Browse</label></td>
  18 +<td class=empty>
  19 +<td><strong>Domain:&nbsp;</strong><input class=form-field id=fil_domain value="" name=fil_domain>&nbsp;<input type=file class=form-field id=fil name=fil></td>
  20 +</tr>
  21 +<tr>
  22 +<td style="vertical-align:top;padding-top:7px;"><input type=radio name=method id=text value="text"><label for="text">Edit</label></td>
  23 +<td class=empty>
  24 +<td><strong>Domain:&nbsp;</strong><input class=form-field id=txt_domain value="" name=txt_domain><br /><textarea id=txt name=txt cols="100" rows="18"></textarea></td>
  25 +</tr>
  26 +</table>
  27 +</div></div>
  28 +<div class=submit><input class=submit-button type=submit name=Submit value="Upload">&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel"></div>
  29 +</form>
0 30 \ No newline at end of file
... ...
templates/uploadproblem.tpl 0 → 100644
  1 +<form name=rew target="{$src}--recordwrite.php" method="POST">
  2 +<div class=clear><div class=main>
  3 +<h4>Committed zone has errors</h4>
  4 +<p><strong>Zone:</strong> <span class=highlight>{$zone}</span><br />
  5 +<strong>Chosen method:</strong> {$method}</p><p>The zonefile is OK, but the import procedure has errors.<br />Please check it, fix it, and try again.</p>
  6 +<p><strong>Output:</strong></p>
  7 +<pre>{section name=i loop=$problem}
  8 +{$problem[i]}
  9 +{/section}</pre>
  10 +</div></div>
  11 +</form>
... ...
templates/uploadreview.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +<h4>Review the imported zone</h4>
  3 +<p><strong>Zone:</strong> <span class=highlight>{$zone}</span><br />
  4 +<strong>Chosen method:</strong> {$method}</p>
  5 +<p><strong>Preview your imported zone:</strong></p>
  6 +<textarea readonly autofocus wrap="off" cols="116" rows="30" class=ro>{section name=i loop=$output}
  7 +{$output[i]}
  8 +{/section}</textarea>
  9 +<p>Check and edit your imported zone between your <a href="zonelist.php" class=attention>master zones</a></p>
  10 +</div></div>
... ...
templates/userlistread.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +{if $admin == 'yes'}<p><a class=new id=new href="{$src}newuser.php">Create a new user</a></p>{/if}
  3 +<table style="min-width:420;">
  4 +<tr>
  5 +<th>Username</th>
  6 +<th>Full name</th>
  7 +<th>Admin</th>
  8 +<th></th>
  9 +<th colspan=2>Action</th>
  10 +</tr>
  11 +{section name=i loop=$userlist}
  12 +<tr>
  13 +<td align=center>{$userlist[i].username}</td>
  14 +<td align=center>{$userlist[i].realname}</td>
  15 +{if $userlist[i].admin == "yes"}<td class=ok title=Yes alt=Yes>&nbsp;</td>
  16 +{elseif $userlist[i].admin == "no"}<td class=no title=No alt=No>&nbsp;</td>
  17 +{/if}
  18 +<td class=empty></td>
  19 +{if $userlist[i].username != "admin"}
  20 +<td class=ed><a href="{$src}user.php?i={$userlist[i].id}" title="Edit user" alt="Edit user">&nbsp;</a></td>
  21 +<td class=del><a href="{$src}deleteuser.php?i={$userlist[i].id}" title="Delete user" alt="Delete user">&nbsp;</a></td>
  22 +{else}
  23 +<td class=no title="Cannot edit" alt="Cannot edit">&nbsp;</td>
  24 +<td class=no title="Cannot delete" alt="Cannot delete">&nbsp;</td>
  25 +{/if}
  26 +</tr>
  27 +{/section}
  28 +</table>
  29 +</div></div>
  30 +{include file="pages.tpl"}
... ...
templates/userread.tpl 0 → 100644
  1 +<div class=clear><div class=main><h4>Edit user's credentials:</h4>
  2 +<form name=form1 method="post" action="{$src}user.php?i={$user.id}" id=new>
  3 +<table width=580>
  4 +<tr>
  5 +<td align=right width=120><strong>Username:</strong></td>
  6 +<td colspan=2 class=highlight>{$user.username}</td>
  7 +<th width=180>Password quality meter<div class=pwc id=pwc>Won't modified!</div></th>
  8 +</tr>
  9 +<tr>
  10 +<td align=right width=120><strong>Full name:</strong></td>
  11 +<td colspan=2><input type=text name=realname class=form-field value="{$user.realname}" autofocus tabindex=1</td>
  12 +<td rowspan=2 id=pwmeter class=nok width=180 title="Won't modified!" alt="Won't modified!"></td>
  13 +</tr>
  14 +<tr>
  15 +<td align=right width=120><strong>Admin rights:</strong></td>
  16 +<td colspan=2 height=32 valign=bottom>
  17 +<input type=radio name=admin id=adminy value="yes"{if $user.admin} checked="checked" tabindex=2{/if} /><label for="adminy">yes</label>&nbsp;&nbsp;
  18 +<input type=radio name=admin id=adminn value="no"{if !$user.admin} checked="checked" tabindex=2{/if} /><label for="adminn">no</label><input type=hidden name=password id=pwmd5n>
  19 +</td>
  20 +</tr>
  21 +</table>
  22 +<div class=submit><input class=submit-button type=submit name=Submit value="Save" id=submit tabindex=5>&nbsp;<input type=button class=submit-button id=cancel value="Cancel" name ="cancel" tabindex=6></div>
  23 +</form>
  24 +<table width=580>
  25 +<tr>
  26 +<td align=right width=120><strong>New password:</strong></td>
  27 +<td><input type=password name=password_one class=form-field id=pass1 autofocus tabindex=3></td>
  28 +<td width=180></td>
  29 +</tr>
  30 +<tr>
  31 +<td align=right width=120><strong>Confirm it:</strong></td>
  32 +<td><input type=password name=confirm_password class=form-field disabled id=pass2 tabindex=4></td>
  33 +<td width=180></td>
  34 +</tr>
  35 +{if $success}<tr><td colspan=3><hr /></td></tr><tr><td colspan=3 align=center><span class=attention>{$success}</span></td></tr>{/if}
  36 +</table>
  37 +{if $zonelist}<table width=580><tr>
  38 +<td colspan=3><hr /></td>
  39 +</tr>
  40 +<tr>
  41 +<th colspan=3><p>Master zones owned by this user:</p></th>
  42 +</tr>
  43 +<tr>
  44 +<th>Name</th>
  45 +<th>Serial</th>
  46 +<th>Action</th>
  47 +</tr>
  48 +{section name=i loop=$zonelist}
  49 +<tr>
  50 +<td align=center>{$zonelist[i].name}</td>
  51 +<td align=center>{$zonelist[i].serial}</td>
  52 +<td class=ed><a href="{$src}record.php?i={$zonelist[i].id}">&nbsp;</a></td>
  53 +</tr>{/section}</table>{/if}
  54 +{if $szonelist}<table width=580><tr>
  55 +<td colspan=3><hr /></td>
  56 +</tr>
  57 +<tr>
  58 +<th colspan=3><p>Slave zones owned by this user:</p></th>
  59 +</tr>
  60 +<tr>
  61 +<th>Name</th>
  62 +<th>Master</th>
  63 +<th>Action</th>
  64 +</tr>
  65 +{section name=i loop=$szonelist}
  66 +<tr>
  67 +<td align=center>{$szonelist[i].name}</td>
  68 +<td align=center>{$szonelist[i].master}</td>
  69 +<td class=ed><a href="{$src}slave_record.php?i={$szonelist[i].id}">&nbsp;</a></td>
  70 +</tr>{/section}</table>{/if}
  71 +<input type=hidden name=bad id=bad value="The password is too short">
  72 +<input type=hidden name=nok id=nok value="Won't modified!">
  73 +<input type=hidden name=notenough id=notenough value="Need to be longer!">
  74 +<input type=hidden name=almost id=almost value="Need to be complex and/or longer!">
  75 +<input type=hidden name=enough id=enough value="Complexity is fair">
  76 +<input type=hidden name=perfect id=perfect value="Complexity is perfect">
  77 +<input type=hidden name=notempty id=notempty value=0>
  78 +</div></div>
... ...
templates/zonepview.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +<p><strong>Zone: <span class=highlight>{$zonename}</span></strong></p>
  3 +<p><strong>Type: </strong>{$zonetype}<br /><strong>Owner: </strong>{$owner}</p>
  4 +<textarea readonly autofocus wrap="off" cols="116" rows="30" class=ro>{if $zonedef}{$zonedef}{else}Zone cannot load{/if}</textarea>
  5 +</div></div>
... ...
templates/zoneread.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +{if $admin == 'yes'}<p><a class=new id=new href="{$src}newzone.php">Create a new master zone</a></p>{else}<h4>List of your master zones</h4>{/if}
  3 +{if $zonelist}<table style="min-width:600">
  4 +<tr>
  5 +<th>Name</th>
  6 +<th>Serial</th>
  7 +<th>Changed</th>
  8 +<th>&nbsp;</th>
  9 +<th colspan=2>Secure</th>
  10 +<th>&nbsp;</th>
  11 +<th colspan=2>Valid</th>
  12 +<th>&nbsp;</th>
  13 +<th colspan=2>Action</th>
  14 +</tr>
  15 +{section name=i loop=$zonelist}
  16 +<tr>
  17 +<td>{$zonelist[i].name}</td>
  18 +<td>{$zonelist[i].serial}</td>
  19 +
  20 +{if $zonelist[i].updated == "yes"}<td class=ok title=Yes alt=Yes>&nbsp;</td>
  21 +{elseif $zonelist[i].updated == "no"}<td class=no title=No alt=No>&nbsp;</td>
  22 +{else}<td class=some title=Unknown alt=Unknown></td>
  23 +{/if}
  24 +<td class=empty>&nbsp;</td>
  25 +{if $zonelist[i].secured == "yes"}<td class=ok title=Yes alt=Yes>&nbsp;</td>
  26 +{if $zonelist[i].valid == "yes" and $zonelist[i].updated == "no"}<td class=view><a alt="View zone as secured" title="View zone as secured" href="{$src}zoneview.php?i={$zonelist[i].id}&s=1">&nbsp;</a></td>
  27 +{else}<td class=empty></td>
  28 +{/if}
  29 +{elseif $zonelist[i].secured == "no"}<td colspan=2 class=no title=No alt=No></td>
  30 +{/if}
  31 +<td class=empty>&nbsp;</td>
  32 +{if $zonelist[i].valid == "yes"}<td class=ok title=Yes alt=Yes>&nbsp;</td>{if $zonelist[i].updated == "no"}<td class=view><a alt="View zone as plain" title="View zone as plain" href="{$src}zoneview.php?i={$zonelist[i].id}&s=0">&nbsp;</a></td>{else}<td class=preview><a alt="Preview zone" title="Preview zone" href="{$src}zonepview.php?i={$zonelist[i].id}&s=0">&nbsp;</a></td>{/if}
  33 +{elseif $zonelist[i].valid == "no"}<td class=nok title=Problem alt=Problem></td><td class=empty></td>
  34 +{else}<td class=some title=Maybe alt=Maybe></td><td class=check><a alt="Check zone" title="Check zone" href="{$src}zonelist.php?i={$zonelist[i].id}&check=y{if $pages}&page={$current_page}{/if}">&nbsp;</a></td>
  35 +{/if}
  36 +<td class=empty>&nbsp;</td>
  37 +<td class=ed><a title="Edit zone" alt="Edit zone" href="{$src}record.php?i={$zonelist[i].id}">&nbsp;</a></td>
  38 +<td class=del><a alt="Remove zone" title="Remove zone" href="{$src}deletezone.php?i={$zonelist[i].id}{if $pages}&page={$current_page}{/if}">&nbsp;</a></td>
  39 +</tr>
  40 +{/section}
  41 +</table>{else}<p>You don't have master zones.</p>{/if}
  42 +</div></div>
  43 +{include file="pages.tpl"}
... ...
templates/zoneview.tpl 0 → 100644
  1 +<div class=clear><div class=main>
  2 +<p><strong>Zone: <span class=highlight>{$zonename}</span></strong></p>
  3 +<p><strong>Type: </strong>{$zonetype}<br /><strong>Owner: </strong>{$owner}</p>
  4 +<textarea readonly autofocus wrap="off" cols="116" rows="30" class=ro>{if $zonedef}{$zonedef}{else}Zone cannot load{/if}</textarea>
  5 +</div></div>
... ...