<?
ini_set
('max_execution_time'300);

$required = array(
    
'domain'    => 'domain name',
    
'network_admin'    => "network admin's email",
    
'dns_primary'    => 'primary DNS server IP',
    );

if (
$zone && $zone array_map('stripslashes'array_map('htmlspecialchars'$zone))) {
    foreach (
$required as $tmpfield => $fieldtext) {
        if (!
$zone[$tmpfield])
            
$missing[] = $fieldtext;
        }
    }

foreach (array(
'refresh''retry''expire''ttl') as $timefield) {
    }

function 
format_hostname($hostname$domain='') {
    if (
$domain) {
        
$domain    preg_replace('/\./''\.'$domain);

        if (
preg_match("/(.*)\.$domain\.*$/i"$hostname$m)) {
            
$hostname $m[1];
            }
        }
    else {
        
$hostname preg_replace('/@/''.'$hostname);
        
$hostname preg_replace('/\.*$/''.'$hostname);
        }

    
$hostname preg_replace('/[^0-9a-z.-]/i'''$hostname);

    return 
strtolower($hostname);
    }
?>
<meta name="author" value="Peter Lowe; pgl@yoyo.org">
<meta name="description" value="a simple script with which to convert a hosts file to BIND zone file format">
<meta name="keywords" value="bind, zone files, hosts files, nameserver, nameservers, ad blocking, blocking ads, ad servers, ads, banners, privacy, blocking spyware, mac hosts">
<meta name="cabal" value="">

<title>
BIND zone file creator
</title>

<?=$style_head?>

<style type="text/css">
<!--

td.example {
    font-size: 10px;
    color: #000080;
    padding-bottom: 8px;
    padding-top: 0px;
    }

-->
</style>

</head>

<body>

<p>
    [ <a href="index.php">back to the ad server index page</a>
    | <a href="bind-zone-file-creator.phps">php source</a>
    | <a href="hosts2bind.php">convert hosts files to BIND config files</a>
    ]

<p>Using the form below, you can create a zone file for use with the BIND DNS server. It's pretty basic, but it allows you to import an existing hosts file as the list of A records set up. This is useful for things like <a href="index.php">ad blocking</a>, as it is much more efficient than distributing hosts files around a network.

<p><b style="color: #800000;">Notes:</b>

<ul>
<li>To convert a hosts file, you either need to paste it into the text area, or choose a file to upload.

<li>The maximum file upload size is 5 MB, and the maximum amount of data you can put in the textarea is 9 MB, hopefully enough for a hosts file. If your hosts file is bigger than this, have a look through the ODP's <a href="http://dmoz.org/Computers/Software/File_Management/File_Splitters/">File Splitters</a> category for an application that will split it into smaller chunks.

<li>All hostnames found are assumed to belong to the specified domain. Fully qualified hostnames are considered to be those ending in the domain, which is stripped off before adding to the zone file. eg, if the domain submitted was "example.com", a hostname like "charlie.example.com" would be seen as fully qualified and be included as just "charlie".

<li>Hosts are converted to lowercase before output.

<li>The fields below are used for various parts of the zone file. Required fields are in <b class=blue>bold</b>.

<li>For more information about BIND zone files, there's a pretty good overview at <a href="http://support.algx.net/cst/dns/dns2.html">Allegiance Internet</a> that should answer most questions, and the <a href="http://www.isc.org/products/BIND/docs/bind8.2_master-file.html">official documentation</a> describes the format in detail. You should really have a general understanding <a href="http://www.oreilly.com/catalog/dns4/">DNS as a whole</a> of DNS as a whole if you want to make sense of everything, though.

<li>If you're thinking of using BIND to <a href="index.php">block ads</a>, you might find this <a href="null.zone.file">null zone file</a> useful.

<? if ($missing) { ?>

<li class=red>Please fill in the missing required fields: <b class=red><?=join(', '$missing)?></b>

<?    ?>

</ul>

<p style="padding-left: 20px;">
<table cellpadding=3 cellspacing=1>

<tr>
<td>
    <table cellpadding=2 cellspacing=1 style="border: 1px solid #444444;" bgcolor="#EEEEEE">

    <form action="<?=$PHP_SELF?>" method=post enctype="multipart/form-data">

    <tr>
    <td class=green>Basic data:</td>
    <td><b class=<?=($zone && !$zone['domain'] ? 'red' 'blue')?>>Domain name</b></td>
    <td><b class=<?=($zone && !$zone['network_admin'] ? 'red' 'blue')?>>Admin email</b> <sup class=footnote>1</sup></td>
    </tr>

    <tr>
    <td style="padding-bottom: 0px;">&nbsp;</td>
    <td style="padding-bottom: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[domain]" value="<?=$zone['domain']?>"></td>
    <td style="padding-bottom: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[network_admin]" value="<?=$zone['network_admin']?>"></td>
    </tr>

    <tr>
    <td class=example>&nbsp;</td>
    <td class=example><i style="color: black;">eg,</i> example.com</td>
    <td class=example><i style="color: black;">eg,</i> hostmaster@example.com</td>
    </tr>

    <tr>
    <td class=green>DNS servers: <sup class=footnote>2</sup></td>
    <td><b class=<?=($zone && !$zone['dns_primary'] ? 'red' 'blue')?>>Primary</b></td>
    <td class=blue>Secondary</td>
    </tr>

    <tr>
    <td style="padding-bottom: 0px; padding-top: 0px;">&nbsp;</td>
    <td style="padding-bottom: 0px; padding-top: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[dns_primary]" value="<?=$zone['dns_primary']?>"></td>
    <td style="padding-bottom: 0px; padding-top: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[dns_secondary]" value="<?=$zone['dns_secondary']?>"></td>
    </tr>

    <tr>
    <td class=example>&nbsp;</td>
    <td class=example><i style="color: black;">eg,</i> ns1.example.net</td>
    <td class=example><i style="color: black;">eg,</i> ns2.example.net</td>
    </tr>

    <tr>
    <td class=green>Mail servers: <sup class=footnote>3</sup></td>
    <td class=blue>Primary</td>
    <td class=blue>Backup</td>
    </tr>

    <tr>
    <td style="padding-bottom: 0px; padding-top: 0px;">&nbsp;</td>
    <td style="padding-bottom: 0px; padding-top: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[mx_primary]" value="<?=$zone['mx_primary']?>"></td>
    <td style="padding-bottom: 0px; padding-top: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[mx_backup]" value="<?=$zone['mx_backup']?>"></td>
    </tr>

    <tr>
    <td style="padding-bottom: 8px; padding-top: 0px;">&nbsp;</td>
    <td class=example><i style="color: black;">eg,</i> mail.example.com</td>
    <td class=example><i style="color: black;">eg,</i> mail-spool.example.com</td>
    </tr>

    <tr>
    <td class=green>Time periods:<sup class=footnote>4</sup></td>
    <td class=blue>Refresh</td>
    <td class=blue>Retry</td>
    </tr>

    <tr>
    <td style="padding-bottom: 0px; padding-top: 0px;">&nbsp;</td>
    <td style="padding-bottom: 0px; padding-top: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[refresh]" value="<?=($zone['refresh'] ? $zone['refresh'] : 28800)?>"></td>
    <td style="padding-bottom: 0px; padding-top: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[retry]" value="<?=($zone['retry'] ? $zone['retry'] : 7200)?>"></td>
    </tr>

    <tr>
    <td>&nbsp;</td>
    <td class=blue>Expire</td>
    <td class=blue>Min TTL</td>
    </tr>

    <tr>
    <td style="padding-bottom: 0px; padding-top: 0px;">&nbsp;</td>
    <td style="padding-bottom: 0px; padding-top: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[expire]" value="<?=($zone['expire'] ? $zone['expire'] : 864000)?>"></td>
    <td style="padding-bottom: 0px; padding-top: 0px;" width=180><input style="width: 100%;" size=30 type=text name="zone[ttl]" value="<?=($zone['ttl'] ? $zone['ttl'] : 86400)?>"></td>
    </tr>

    <tr>
    <td style="padding-top: 12px;" colspan=2 align=right>Now either upload a hosts file (max 5 MB):</td>
    <td style="padding-top: 12px;"><input type=file name="hostsfile" style="width: 170px;"></td>
    </tr>

    <tr>
    <td colspan=2 align=center>... or paste the contents into the field below &dArr;</td>
    <td align=center><input type=submit value="convert to zone file"></td>
    </tr>

    <tr><td colspan=3>
    <textarea name="zone[hosts_data]" rows=8 cols=100 style="width: 450px;"><?=$zone['hosts_data']?></textarea>
    </td></tr>

    </form>

    </table>
</td>

<td valign=top>
    <table cellpadding=3 cellspacing=5 width=180>

    <tr>
    <td class=footnote valign=top><sup class=footnote>1</sup></td>
    <td class=footnote>Required for the <a href="http://support.algx.net/cst/dns/dns2.html#SOA">Start Of Authority</a> record</td>
    </tr>

    <tr>
    <td class=footnote valign=top><sup class=footnote>2</sup></td>
    <td class=footnote>Whilst only one DNS server is required, it's highly recommended to set up a secondary server</td>
    </tr>

    <tr>
    <td class=footnote valign=top><sup class=footnote>3</sup></td>
    <td class=footnote>The mail servers are responsible for all mail for your domain. Not specifying at least one causes mail to be sent to individual hosts.</td>
    </tr>

    <tr>
    <td class=footnote valign=top><sup class=footnote>4</sup></td>
    <td class=footnote>Optional values in seconds; it's safe to ignore these if you want to.</td>
    </tr>

    </table>
</td>
</tr>

</table>

<? if ($zone && !$missing) { ?>

<p><hr size=1 noshade>

<pre>
; BIND db file for <?=$zone['domain']?>


$TTL <?=$zone['ttl']?>


@       IN      SOA     <?=format_hostname($zone['dns_primary'])?>      <?=format_hostname($zone['network_admin'])?> (
                        <?=date('Ymd')?>01    ; serial number YYMMDDNN
                        <?=sprintf('%-15d'$zone['refresh'])?> ; Refresh
                        <?=sprintf('%-15d'$zone['retry'])?> ; Retry
                        <?=sprintf('%-15d'$zone['expire'])?> ; Expire
                        <?=sprintf('%-15d'$zone['ttl'])?> ; Min TTL
            )

                NS      <?=format_hostname($zone['dns_primary'])?> 
<?   if ($zone['dns_secondary']) { ?>
                NS      <?=format_hostname($zone['dns_secondary'])?> 
<? } if ($zone['mx_primary']) { ?>

                MX      10 <?=format_hostname($zone['mx_primary'])?>

<? } if ($zone['mx_backup']) { ?>
                MX      20 <?=format_hostname($zone['mx_backup'])?>

<? ?>


$ORIGIN <?=format_hostname($zone['domain'])?>


<?
    
if ($hostsfile || $zone['hosts_data']) foreach ((is_uploaded_file($hostsfile) ? file($hostsfile) : preg_split('/[\r\n]/ism'$zone['hosts_data'])) as $line) {
        
// trim comments off the end of lines and skip blanks
        
if (!$line preg_replace('/(^\s+|\s*#.*$)/'''$line))
            continue;

        
// get the ip address and hostnames, or skip
        
if (!preg_match('/^((?:\d{1,3}\.){3}\d{1,3})\s+(.*)/'$line$m))
            continue;

        
// get the ip and split the hostnames into an array
        
$ip    $m[1];
        
$hosts    preg_split('/\s+/'$m[2], -1PREG_SPLIT_NO_EMPTY);

        foreach (
$hosts as $host) {
            
$host    format_hostname($host$zone['domain']);

            
// skip duplicate hosts already assigned to this IP
            
if ($seen_hosts[$host] == $ip)
                continue;

            
// add host to list of existing if we got this far
            
$seen_hosts[$host] = $ip;
?>
<?=$host?>
    IN    A    <?=$ip?> 
<?
            
}
        }
?>
</pre>
<?    ?>

</body>

</html>