enable CardFortress in test database, #71513
[freeside.git] / FS / FS / domain_record.pm
index e975cac..e180e4b 100644 (file)
@@ -1,16 +1,14 @@
 package FS::domain_record;
+use base qw(FS::Record);
 
 use strict;
-use vars qw( @ISA $noserial_hack $DEBUG );
+use vars qw( $noserial_hack $DEBUG $me );
 use FS::Conf;
-#use FS::Record qw( qsearch qsearchs );
-use FS::Record qw( qsearchs dbh );
-use FS::svc_domain;
+use FS::Record qw( qsearchs dbh ); #qsearch
 use FS::svc_www;
 
-@ISA = qw(FS::Record);
-
 $DEBUG = 0;
+$me = '[FS::domain_record]';
 
 =head1 NAME
 
@@ -51,6 +49,8 @@ supported:
 
 =item recdata - data for this entry
 
+=item ttl - time to live
+
 =back
 
 =head1 METHODS
@@ -59,7 +59,7 @@ supported:
 
 =item new HASHREF
 
-Creates a new entry.  To add the example to the database, see L<"insert">.
+Creates a new entry.  To add the entry to the database, see L<"insert">.
 
 Note that this stores the hash reference, not a distinct copy of the hash it
 points to.  You can ask the object for a copy with the I<hash> method.
@@ -229,7 +229,7 @@ sub replace {
 
 =item check
 
-Checks all fields to make sure this is a valid example.  If there is
+Checks all fields to make sure this is a valid entry.  If there is
 an error, returns the error, otherwise returns false.  Called by the insert
 and replace methods.
 
@@ -250,17 +250,27 @@ sub check {
   return "Unknown svcnum (in svc_domain)"
     unless qsearchs('svc_domain', { 'svcnum' => $self->svcnum } );
 
-  $self->reczone =~ /^(@|[a-z0-9\.\-\*]+)$/i
-    or return "Illegal reczone: ". $self->reczone;
-  $self->reczone($1);
+  my $conf = new FS::Conf;
+
+  if ( $conf->exists('zone-underscore') ) {
+    $self->reczone =~ /^(@|[a-z0-9_\.\-\*]+)$/i
+      or return "Illegal reczone: ". $self->reczone;
+    $self->reczone($1);
+  } else {
+    $self->reczone =~ /^(@|[a-z0-9\.\-\*]+)$/i
+      or return "Illegal reczone: ". $self->reczone;
+    $self->reczone($1);
+  }
 
   $self->recaf =~ /^(IN)$/ or return "Illegal recaf: ". $self->recaf;
   $self->recaf($1);
 
-  $self->rectype =~ /^(SOA|NS|MX|A|PTR|CNAME|TXT|_mstr)$/
-    or return "Illegal rectype (only SOA NS MX A PTR CNAME TXT recognized): ".
-              $self->rectype;
-  $self->rectype($1);
+  $self->ttl =~ /^([0-9]{0,6})$/ or return "Illegal ttl: ". $self->ttl;        
+  $self->ttl($1); 
+
+  my %rectypes = map { $_=>1 } ( @{ $self->rectypes }, '_mstr' );
+  return 'Illegal rectype: '. $self->rectype
+    unless exists $rectypes{$self->rectype} && $rectypes{$self->rectype};
 
   return "Illegal reczone for ". $self->rectype. ": ". $self->reczone
     if $self->rectype !~ /^MX$/i && $self->reczone =~ /\*/;
@@ -283,23 +293,42 @@ sub check {
     $self->recdata =~ /^((\d{1,3}\.){3}\d{1,3})$/
       or return "Illegal data for A record: ". $self->recdata;
     $self->recdata($1);
-  } elsif ( $self->rectype eq 'PTR' ) {
-    $self->recdata =~ /^([a-z0-9\.\-]+)$/i
-      or return "Illegal data for PTR record: ". $self->recdata;
+  } elsif ( $self->rectype eq 'AAAA' ) {
+    $self->recdata =~ /^([\da-z:]+)$/
+      or return "Illegal data for AAAA record: ". $self->recdata;
     $self->recdata($1);
+  } elsif ( $self->rectype eq 'PTR' ) {
+    if ( $conf->exists('zone-underscore') ) {
+      $self->recdata =~ /^([a-z0-9_\.\-]+)$/i
+        or return "Illegal data for PTR record: ". $self->recdata;
+      $self->recdata($1);
+    } else {
+      $self->recdata =~ /^([a-z0-9\.\-]+)$/i
+        or return "Illegal data for PTR record: ". $self->recdata;
+      $self->recdata($1);
+    }
   } elsif ( $self->rectype eq 'CNAME' ) {
     $self->recdata =~ /^([a-z0-9\.\-]+|\@)$/i
       or return "Illegal data for CNAME record: ". $self->recdata;
     $self->recdata($1);
   } elsif ( $self->rectype eq 'TXT' ) {
-    $self->recdata =~ /^((?:\S+)|(?:".+"))$/
-      or return "Illegal data for TXT record: ". $self->recdata;
-    $self->recdata($1);
+    if ( $self->recdata =~ /^((?:\S+)|(?:".+"))$/ ) {
+      $self->recdata($1);
+    } else {
+      $self->recdata('"'. $self->recdata. '"'); #?
+    }
+    #  or return "Illegal data for TXT record: ". $self->recdata;
+  } elsif ( $self->rectype eq 'SRV' ) {                                        
+    $self->recdata =~ /^(\d+)\s+(\d+)\s+(\d+)\s+([a-z0-9\.\-]+)$/i             
+      or return "Illegal data for SRV record: ". $self->recdata;               
+    $self->recdata("$1 $2 $3 $4");                        
   } elsif ( $self->rectype eq '_mstr' ) {
     $self->recdata =~ /^((\d{1,3}\.){3}\d{1,3})$/
       or return "Illegal data for _master pseudo-record: ". $self->recdata;
   } else {
-    die "ack!";
+    warn "$me no specific check for ". $self->rectype. " records yet";
+    $error = $self->ut_text('recdata');
+    return $error if $error;
   }
 
   $self->SUPER::check;
@@ -339,13 +368,6 @@ sub increment_serial {
 
 Returns the domain (see L<FS::svc_domain>) for this record.
 
-=cut
-
-sub svc_domain {
-  my $self = shift;
-  qsearchs('svc_domain', { svcnum => $self->svcnum } );
-}
-
 =item zone
 
 Returns the canonical zone name.
@@ -402,6 +424,18 @@ sub reverse_record {
     or new FS::domain_record { %hash, 'recdata' => $self->zone.'.' };
 }
 
+=item rectypes
+
+=cut
+#http://en.wikipedia.org/wiki/List_of_DNS_record_types
+#DHCID?  other things?
+sub rectypes {
+  [ qw(SOA A AAAA CNAME MX NS PTR SPF SRV TXT), #most common types
+    #qw(DNAME), #uncommon types
+    qw(DLV DNSKEY DS NSEC NSEC3 NSEC3PARAM RRSIG), #DNSSEC types
+  ];
+}
+
 =back
 
 =head1 BUGS