123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- <?php declare(strict_types=1);
- function parseZoneFile(string $zone_content, array $types, bool|string $filter_domain = false, bool $filter_include_subdomains = true): array {
- $parsed_zone_content = [];
- foreach (explode(LF, $zone_content) as $zone_line) {
- if ($zone_line === '' OR str_starts_with($zone_line, ';'))
- continue; // Ignore empty lines and comments
- $elements = preg_split('/[\t ]+/', $zone_line, 4);
- if ($filter_domain !== false AND match ($filter_include_subdomains) {
- true => !str_ends_with($elements[0], $filter_domain),
- false => $elements[0] !== $filter_domain,
- })
- continue; // Ignore records for other domains
- if (!in_array($elements[2], $types, true))
- continue; // Ignore records generated by Knot
- array_push($parsed_zone_content, $elements);
- }
- return $parsed_zone_content;
- }
- function knotc(array $cmds, array &$output = NULL, int &$return_code = NULL): void {
- exescape([
- CONF['dns']['knotc_path'],
- '--blocking',
- '--timeout',
- '20',
- '--',
- ...$cmds,
- ], $output, $return_code);
- }
- function knotcConfExec(array $cmds): void {
- knotc(['conf-begin'], $output['begin'], $code['begin']);
- if ($code['begin'] !== 0)
- output(500, 'knotcConfExec: <code>knotc</code> failed with exit code <samp>' . $code['begin'] . '</samp>: <samp>' . $output['begin'][0] . '</samp>.');
- foreach ($cmds as $cmd) {
- knotc($cmd, $output['op'], $code['op']);
- if ($code['op'] !== 0) {
- knotc(['conf-abort']);
- output(500, 'knotcConfExec: <code>knotc</code> failed with exit code <samp>' . $code['op'] . '</samp>: <samp>' . $output['op'][0] . '</samp>.');
- }
- }
- knotc(['conf-commit'], $output['commit'], $code['commit']);
- if ($code['commit'] !== 0) {
- knotc(['conf-abort']);
- output(500, 'knotcConfExec: <code>knotc</code> failed with exit code <samp>' . $code['commit'] . '</samp>: <samp>' . $output['commit'][0] . '</samp>.');
- }
- }
- function knotcZoneExec(string $zone, array $cmd, string $action = NULL): void {
- $action = checkAction($action ?? $_POST['action']);
- knotc(['zone-begin', $zone], $output['begin'], $code['begin']);
- if ($code['begin'] !== 0)
- output(500, 'knotcZoneExec: <code>knotc</code> failed with exit code <samp>' . $code['begin'] . '</samp>: <samp>' . $output['begin'][0] . '</samp>.');
- knotc(['zone-' . $action . 'set', $zone, ...$cmd], $output['op'], $code['op']);
- if ($code['op'] !== 0) {
- knotc(['zone-abort', $zone]);
- output(500, 'knotcZoneExec: <code>knotc</code> failed with exit code <samp>' . $code['op'] . '</samp>: <samp>' . $output['op'][0] . '</samp>.');
- }
- knotc(['zone-commit', $zone], $output['commit'], $code['commit']);
- if ($code['commit'] !== 0) {
- knotc(['zone-abort', $zone]);
- output(500, 'knotcZoneExec: <code>knotc</code> failed with exit code <samp>' . $code['commit'] . '</samp>: <samp>' . $output['commit'][0] . '</samp>.');
- }
- }
- function checkIpFormat(string $ip): string {
- return match ($ip) {
- filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) => 'AAAA',
- filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) => 'A',
- default => output(403, _('IP address malformed.')),
- };
- }
- function checkAbsoluteDomainFormat(string $domain): void { // If the domain must end with a dot
- if (!filter_var($domain, FILTER_VALIDATE_DOMAIN) OR preg_match('/^(?=^.{1,254}$)([a-z0-9_-]{1,63}\.){2,127}$/D', $domain) !== 1)
- output(403, _('Domain malformed.'));
- }
- function formatEndWithDot(string $str): string {
- if (!str_ends_with($str, '.'))
- $str .= '.';
- return $str;
- }
- function formatAbsoluteDomain(string $domain): string {
- $domain = formatEndWithDot(strtolower($domain));
- checkAbsoluteDomainFormat($domain);
- return $domain;
- }
- function checkAction(string $action): string {
- return match ($action) {
- 'add' => '',
- 'delete' => 'un',
- default => output(403, 'Wrong value for action.'),
- };
- }
|