#!/usr/bin/php
<?php

### functions

	function getSerial()
	{	
		$sql="SELECT `value` FROM `var` WHERE `key`='date';";
		$res=DBquery($sql);
		$date=$res->fetch_row();

		if ($date[0]<date("Ymd"))
		{
			DBquery("UPDATE `var` SET `value`=".date('Ymd')." WHERE `key`='date';");
			DBquery("UPDATE `var` SET `value`=1 WHERE `key`='serial';");
		}

		$sql="SELECT `value` FROM `var` WHERE `key`='serial';";
		$res=DBquery($sql);
		$s=$res->fetch_row();
		DBquery("UPDATE `var` SET `value`=`value`+1 WHERE `key`='serial';");
		return date("Ymd").str_pad($s[0],2,"0",STR_PAD_LEFT);
	}

########################################################################

/// init
	global $ini;
	global $node;
	global $force_run;

	require(dirname(__FILE__)."/../include/functions.php");
	check_force_run(1);
	init();

	if (get_ini_opt('confgen','bind-confgen') === '0') { exit(0); }

	check_update('bind_update');

### includes
	require(dirname(__FILE__)."/../include/template.class.php");

### read configuration options

	$defmx=$ini['global']['mx'];
	$defip=$ini['nodeip'][1];

	$confdir=$ini['bind']['confdir'];
	$spf_extra='';
	if (array_key_exists('spf_extra', $ini['bind']))
	{
		$spf_extra=$ini['bind']['spf_extra'];
	}


	//automatic hosts for mail
	$mailhosts=array("mail", "webmail", "smtp", "imap", "imap4", "pop", "pop3");

### generate opendkim records

	$opendkim_keys=array();
	foreach ($ini['opendkim']['key'] as $keyid => $keyval)
	{
		if (is_numeric($keyid))
		{
			// compatibility
			$dkim_selector=$ini['global']['host'].'-'.str_pad($keyid, 2, '0', STR_PAD_LEFT);
		}
		else
		{
			// custom selector
			$dkim_selector=$keyid;
		}
		//$dkim_pubkey=split_domrec_txt("v=DKIM1; k=rsa; p=".$keyval);
		$dkim_pubkey=split_domrec_txt($keyval);
		$opendkim_keys[$dkim_selector]=$dkim_pubkey;
		unset($dkim_selector);
		unset($dkim_pubkey);
	}

### Delete last backup of zones.conf, backup current (if exists)

	if (file_exists($confdir.'/zones.conf.bck'))
	{
		unlink($confdir.'/zones.conf.bck'); 
	}

	if (file_exists($confdir.'/zones.conf'))
	{
		rename($confdir.'/zones.conf',$confdir.'/zones.conf.bck');
	}

### Check zone and zone.bck dir

	if (!(file_exists($confdir.'/zone')))
	{
		mkdir($confdir.'/zone', 0775);
	}
	if (!(file_exists($confdir.'/zone.bck')))
	{
		mkdir($confdir.'/zone.bck', 0775);
	}

### collect DNS data

	logme("bind: Export started");
	
	$sql="SELECT `domain`.`name` AS name,
		IF(`client`.`active`=1, `domain`.`ip`, NULL) as extip,
		TRIM('\n' FROM IFNULL(IF(`client`.`active`=1, `domain`.`mx`, NULL),'$defmx')) as mx,
		'$defmx' as defmx,
		IFNULL(NULLIF(`domain`.`spf`, ''), '~all') AS spf,
		`domain`.`dmarc` AS dmarc,
		`domain`.`transport` AS transport,
		`domain`.`id` AS id,
		IF ((`domain`.`modified` > DATE_SUB(NOW(), INTERVAL 10 MINUTE)), 1, 0) AS changed,
		`client`.`node` AS node,
		`client`.`active` AS cliact
		FROM `domain`
		LEFT JOIN `client` ON `domain`.`clientid`=`client`.`id`
		WHERE `dns`=1 AND `domain`.`active`=1;";// AND client.active=1;

	$res=DBquery($sql) or die(1);
	$n=$res->num_rows;

	//if ($n==0)  exit(1);

### check if hosts or records have changed for the domain

	$changed_dom_rec=array();

	$hcsql="SELECT `domainid`
		FROM `dom_host`
		WHERE (`modified` > DATE_SUB(NOW(), INTERVAL 10 MINUTE));";

	$hcres=DBquery($hcsql) or die(1);
	while ($hcarr = $hcres->fetch_assoc())
	{
		$changed_dom_rec[$hcarr['domainid']]=1;
	}

	$rcsql="SELECT `domainid`
		FROM `dom_records`
		WHERE (`modified` > DATE_SUB(NOW(), INTERVAL 10 MINUTE));";

	$rcres=DBquery($rcsql) or die(1);
	while ($rcarr = $rcres->fetch_assoc())
	{
		$changed_dom_rec[$rcarr['domainid']]=1;
	}

	logme ("bind: Creating $n zones");

### generate zones.conf

	$template = new Template;
	$template->template_dir = $ini['global']['template_dir'];
	$template->compile_dir = $ini['global']['template_dir']."_c";

	$template->assign_md_array($res, 'domains');

### save zones.conf

	fpush($ini['bind']['confdir'].'/zones.conf',$template->fetch('zones.tpl'));

	$res->data_seek(0);

### generate zone files

	$serial=getSerial();

	while ($domain = $res->fetch_assoc())
	{

		if ( $domain['changed']==1 || array_key_exists($domain['id'], $changed_dom_rec ) || (!(file_exists($confdir.'/zone/'.$domain['name']))) || $force_run == 1 )
		{

			$cliact=$domain['cliact'];

			$template->assign('serial',$serial);
	
			$domain['mxarray']=multirow2array($domain['mx']);

			$domain['allips']=array();
			$domain['allips'][$ini['nodeip'][1]]=$ini['nodeip'][1];
			$domain['allips'][$ini['nodeip'][$domain['node']]]=$ini['nodeip'][$domain['node']];

			if ($domain['name']==$ini['global']['domain'])
			{
				foreach($ini['nodeip'] as $nodeip)
				{
					$domain['allips'][$nodeip]=$nodeip;
				}
			}

			if ($domain['extip']=="")
			{
				$domain['ip']=$ini['nodeip'][$domain['node']];
			}
			else
			{
				$domain['ip']=$domain['extip'];
				$domain['allips'][$domain['extip']]=$domain['extip'];
			}

			if (!($domain['dmarc']))
			{
				if ( is_null($domain['transport']) && ($domain['mx']=="$defmx") )
				{
					$domain['dmarc']='p=none; rua=mailto:dmarcreport@'.$domain['name'].';';
				}
				else
				{
					$domain['dmarc']='p=none;';
				}
			}

			$template->assign($domain);

### Assign server/node defaults

			//server defaults
			$template->assign('def_ip',$defip);
			$template->assign('def_domain',$ini['global']['domain']);
			$template->assign('def_host',$ini['global']['host']);
			$template->assign('opendkim_keys',$opendkim_keys);

			$template->assign('sec_ns',$ini['bind']['ns2']);
			$template->assign('spf_extra',$spf_extra);

### Assign node IPs

			$template->assign('nodeips', $ini['nodeip']);
			$template->assign('domain_node_ip',$ini['nodeip'][$domain['node']]);

### Get Hosts (only if client is active, else default)

			$hosts_array=array();
			$hostnames_array=array();

			if ($cliact==1)
			{
	
				$sql="SELECT `host`,
					`ip` AS extip,
					TRIM('\n' FROM IFNULL(`dom_host`.`mx`, '".$defmx."')) AS mx
					FROM `dom_host`
					WHERE `domainid`=".$domain['id']." AND `active`=1;";
				$hres= DBquery($sql);

				while ($hostarray=$hres->fetch_assoc())
				{
					$hostarray['mxarray']=multirow2array($hostarray['mx']);

					$hostarray['allips']=array();
					$hostarray['allips'][$ini['nodeip'][1]]=$ini['nodeip'][1];
					$hostarray['allips'][$ini['nodeip'][$domain['node']]]=$ini['nodeip'][$domain['node']];

					if ($hostarray['extip']=="")
					{
						$hostarray['ip']=$ini['nodeip'][$domain['node']];
					}
					else
					{
						$hostarray['ip']=$hostarray['extip'];
						$hostarray['allips'][$hostarray['extip']]=$hostarray['extip'];
					}

					$hosts_array[]=$hostarray;
					$hostnames_array[]=$hostarray['host'];
				}
			}

### Generate default mail hosts

			if ( is_null($domain['transport']) && ($domain['mx']=="$defmx") )
			{
				foreach ($mailhosts as $mailhost)
				{
					if (!(in_array($mailhost,$hostnames_array)))
					{
						$hosts_array[]=array('host' => $mailhost, 'ip' => $defip, 'allips' => array($defip => $defip), 'mxarray' => array());
					}
				}
			}

### Assign hosts

			$template->assign('hosts',$hosts_array);

### Get Custom DNS records (only if client is active, else default)

			$rres=array();

			if ($cliact==1)
			{
				$sql="SELECT `host`,`type`,`value` FROM `dom_records` WHERE `domainid`=".$domain['id']." AND `active`=1;";
				$rres= DBquery($sql);
				$template->assign_md_array($rres, 'records');
			}
			else
			{
				$emptyarr=array();
				$template->assign('records',$emptyarr);
			}


### Save zone file

			// delete old backup if exists
			if (file_exists($confdir.'/zone.bck/'.$domain['name']))
			{
				unlink($confdir.'/zone.bck/'.$domain['name']);
			}
			
			// move zone file to backup if exists
			if (file_exists($confdir.'/zone/'.$domain['name']))
			{
				rename($confdir.'/zone/'.$domain['name'],$confdir.'/zone.bck/'.$domain['name']);
			}

			fpush($confdir.'/zone/'.$domain['name'],$template->fetch('zone.tpl'));
			$template->clearAllAssign();

### Check zone file validity

			$domname=preg_replace("#[^a-z0-9\-\.]#",'',$domain['name']);
			$zonetest=str_replace('{domain}', $domname, $ini['bind']['zonetest']);

			if (file_exists($confdir.'/zone/'.$domname))
			{
				if (exec_err($zonetest.' 2>/dev/null') != 0)
				{
					unlock_update('bind_update');
					panic('Bind zone error in '.$domain['name']);
				}
			}
			else
			{
				panic('Bind zone file '.$domain['name'].' not found.');
			}
		}
	}

### Check configs

	if (exec_err($ini['bind']['conftest'].' 2>/dev/null') != 0)
	{
		panic("Bind config error");
	}

### reload DNS

	daemons_startstop(array($ini['bind']['name'] => 'reload'));

### reset update flag

	unlock_update('bind_update');

	logme("bind: Export done.");
