#!/usr/bin/perl
#
# tinydns-predata.pl
#
# Data file preprocessor for tinydns
# v0.4 2006-04-17, copyleft Ward Vandewege (ward@pong.be)
# Released under the GPL, v2 or higher (for a copy see http://www.gnu.org)
# Thanks to Peter Pentchev, Mrs. Brisby, Paul Jarc and Jeff King for ideas

# Suggested usage: `tinydns-predata.pl && make` in the 'root' directory of tinydns 
# Alternatively, you could alter the Makefile to say:
# data.cdb: predata
#         /usr/local/bin/tinydns-predata.pl
#         /usr/local/bin/tinydns-data
# Note the change on the first line (data -> predata!)

# IMPORTANT
# You will need to rename your 'data' file to 'predata'. If a 'predata' file
# exists and can be read without problems, the 'data' file will be overwritten.
# You have been warned.
# /IMPORTANT

# Syntax for the 'predata' file:

# 1. Use all syntax you can use in tinydns's data files.  2. Extra syntax: A
# line like: *duplicatefqdn:fqdn will generate a copy of every definition of
# fqdn for duplicatefqdn in the data file. Any line starting with a Q will end
# up unaltered in the output (but without the leading Q, of course). For
# instance, Q*something:somethingelse will put *something:somethingelse
# unaltered in the data file. 

# Limitations:

# 1. This will not work for domain names with characters outside a-z,0-9, and -
# (more specifically, unicode domains)
# 2. If your predata file is very large, this script will use a lot of memory!

# Changelog
# v0.4 (2006-04-17)
# Added support for split-horizon commands
# Bugfix: now truly support domains with dashes (-) in them (thanks to Ron Guerin for reporting this bug!)
# v0.3 (2003-01-27)
# Domains with - in their names will now also be accepted
# Sorting of records in generated data file now more logical - preliminary support for 3-level TLDs like .uk

my %domains;

open(PREDATA,"predata") or die "Can't open 'predata' for input: $!";
my @predata = <PREDATA>;
close(PREDATA) or die "Can't close 'predata' after input: $!";

# First fill domains hash with all info for the domains
foreach(@predata) { 
  my $line = $_;
  next if ($line =~ /^(#|-)/); # Ignore comments
  # Lines started with Q (quoted) will be unaltered, but
  # without the leading Q of course. Thanks Paul Jarc for the idea.
  $line = substr($line,1,length($line)-1) if ($line =~ /^Q/);
  if (($line =~ /^[@\.&+Z=\-'^C:]{1}[^:]*?([^.]*?)\.([^.]*?):/) || # normal lines
      ($line =~ /%.*/)) { # split-horizon lines
    if ($2 eq 'uk') { # the UK has a 3-level DNS name structure
      $domains{"$1.$2.$3"} .= $line if ($line =~ /^[@.&+Z=\-'^C:]{1}[^:]*?([^.]*?)\.([^.]*?)\.([^.]*?):/);
    } else {
      $domains{"$1.$2"} .= $line;
    }
  }
}

# Now look for *'s and duplicate!
foreach (@predata) {
  my $line = $_;
  next if (!($line =~ /^\*/));
  if ($line =~ /.*?([a-zA-Z0-9\-]*?)\.([a-zA-Z0-9]*?):(.*)/) {
    my ($originaldom,$copydom,$copytld) = ($3, $1, $2);
    my $tmp = $domains{$originaldom};
    $tmp =~ s/$originaldom/$copydom\.$copytld/g;
    $domains{"$copydom\.$copytld"} = $tmp;
  }
}

# Finally output the preprocessed data
open(DATA,">data") or die "Can't open 'data' for output: $!";
print DATA <<EOF;
# This file has been auto-generated by the tinydns-predata.pl script
# Don't make any changes here - if you do, they will be overwritten
# automatically on the next run of tinydns-predata.pl
#
# Make your changes in the file 'predata' instead!
#
# See tinydns-predata.pl for the extra syntax you can use in the 'predata' file.
# More info can also be found on http://patch.be/djbdns/tinydns-predata.html

EOF
foreach (sort keys %domains) {
  print DATA "$domains{$_}\n\n";
}
close(DATA) or die "Can't close 'data' after output: $!";

