Net::DRI::Data::Hosts - Handle ordered list of nameservers (name, IPv4 addresses, IPv6 addresses) for Net::DRI


Net-DRI documentation Contained in the Net-DRI distribution.

Index


Code Index:

NAME

Top

Net::DRI::Data::Hosts - Handle ordered list of nameservers (name, IPv4 addresses, IPv6 addresses) for Net::DRI

SYNOPSIS

Top

 use Net::DRI::Data::Hosts;

 my $dh=Net::DRI::Data::Hosts->new();
 $dh->add('ns.example.foo',['1.2.3.4','1.2.3.5']);
 $dh->add('ns2.example.foo',['10.1.1.1']); ## Third element can be an array ref of IPv6 addresses
 ## ->add() returns the object itself, and thus can be chained

 ## Number of nameservers
 print $dh->count(); ## Gives 2

 ## List of names, either all without arguments, or the amount given by the argument
 my @a=$dh->get_names(2); ## Gives ('ns.example.foo','ns2.example.foo')

 ## Details for the nth nameserver (the list starts at 1 !)
 my @d=$dh->get_details(2); ## Gives ('ns2.example.foo',['10.1.1.1'])

 ## Details by name is possible also
 my @d=$dh->get_details('ns2.example.foo');

DESCRIPTION

Top

Order of nameservers is preserved. Order of IP addresses is preserved, but no duplicate IP is allowed.

If you try to add a nameserver that is already in the list, the IP addresses provided will be added to the existing IP addresses (without duplicates)

Hostnames are verified before being used with Net::DRI::Util::is_hostname().

IP addresses are verified with Net::DRI::Util::is_ipv4() and Net::DRI::Util::is_ipv6().

METHODS

Top

new(...)

creates a new instance ; if parameters are given, add() is called with them all at once

new_set(...)

creates a new instance ; if parameters are given, add() is called once for each parameter

clear()

clears the current list of nameservers

set(...)

clears the current list of nameservers, and call add() once for each parameter passed

add(name,[ipv4],[ipv6])

adds a new nameserver with the given name and lists of IPv4 and IPv6 addresses

name()

name of this object (for example for registries having the notion of host groups) ; this has nothing to do with the name(s) of the nameservers inside this object

loid()

local id of this object

get_names(limit)

returns a list of nameservers' names included in this object ; if limit is provided we return only the number of names asked

count()

returns the number of nameservers currently stored in this object

is_empty()

returns 0 if this object has nameservers, 1 otherwise

get_details(pos_or_name)

given an integer (position in the list, we start to count at 1) or a name, we return all details as a 3 element array in list context or only the first element (the name) in scalar context for the nameserver stored at the given position or with the given name ; returns undef if nothing found at the position/with the name given.

SUPPORT

Top

For now, support questions should be sent to:

<netdri@dotandco.com>

Please also see the SUPPORT file in the distribution.

SEE ALSO

Top

http://www.dotandco.com/services/software/Net-DRI/

AUTHOR

Top

Patrick Mevzek, <netdri@dotandco.com>

COPYRIGHT

Top


Net-DRI documentation Contained in the Net-DRI distribution.

## Domain Registry Interface, Implements a list of host (names+ip) with order preserved
##
## Copyright (c) 2005,2006,2007,2008,2009 Patrick Mevzek <netdri@dotandco.com>. All rights reserved.
##
## This file is part of Net::DRI
##
## Net::DRI is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## See the LICENSE file that comes with this distribution for more details.
#
# 
#
####################################################################################################

package Net::DRI::Data::Hosts;

use strict;
use warnings;

use base qw(Class::Accessor::Chained::Fast);

__PACKAGE__->mk_accessors(qw(name loid));

use Net::DRI::Util;

our $VERSION=do { my @r=(q$Revision: 1.18 $=~/\d+/g); sprintf("%d".".%02d" x $#r, @r); };

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

sub new
{
 my $class=shift;
 my $self={ list => [] }; ## list=>[['',[ipv4],[ipv6],{}]+],options=>{}
 bless $self,$class;
 $self->add(@_) if (@_);
 return $self;
}

sub new_set
{
 my $s=shift->new();
 foreach (@_) { $s->add($_); }
 return $s;
}

sub clear
{
 my $s=shift;
 $s->{list}=[];
}

sub set
{
 my $s=shift;
 $s->{list}=[];
 foreach (@_) { $s->add($_); }
 return $s;
}

sub add
{
 my ($self,$in,$e1,$e2,$ipall,$rextra)=@_;
 ($ipall,$rextra)=(undef,$ipall)  if (defined($ipall) && ref($ipall));
 return unless (defined($in) && $in);

 if (ref $in eq 'ARRAY')
 {
  return $self->add(@$in);
 }

 if (defined $e2 && $e2)
 {
  $self->_push($in,$e1,$e2,$ipall,$rextra);
  return $self;
 }

 if (defined $e1 && $e1)
 {
  $self->_push($in,_separate_ips($e1,$ipall),$ipall,$rextra);
  return $self;
 }

 $self->_push($in,[],[],1,$rextra);
 return $self;
}

sub _separate_ips
{
 my (@ip4,@ip6);
 my $ipall=pop(@_);
 $ipall=0 unless defined($ipall);
 foreach my $ip (map {ref($_)? @{$_} : $_} @_)
 {
  ## We keep only the public ips
  push @ip4,$ip if Net::DRI::Util::is_ipv4($ip,1-$ipall);
  push @ip6,$ip if Net::DRI::Util::is_ipv6($ip,1-$ipall);
 }
 return (\@ip4,\@ip6);
}

sub _push
{
 my ($self,$name,$ipv4,$ipv6,$ipall,$rextra)=@_;
 $ipall=0 unless defined $ipall;
 chop($name) if (defined $name && $name && $name=~m/\.$/);
 return unless Net::DRI::Util::is_hostname($name);
 $name=lc($name); ## by default, hostnames are case insensitive

 ## We keep only the public ips
 my @ipv4=grep { Net::DRI::Util::is_ipv4($_,1-$ipall) } ref $ipv4 ? @$ipv4 : ($ipv4);
 my @ipv6=grep { Net::DRI::Util::is_ipv6($_,1-$ipall) } ref $ipv6 ? @$ipv6 : ($ipv6);

 if ($self->count() && defined $self->get_details($name)) ## name already here, we append IP
 {
  foreach my $el (@{$self->{list}})
  {
   next unless ($el->[0] eq $name);
   unshift @ipv4,@{$el->[1]};
   unshift @ipv6,@{$el->[2]};
   $el->[1]=_remove_dups_ip(\@ipv4);
   $el->[2]=_remove_dups_ip(\@ipv6);
   if (defined $el->[3] || defined $rextra)
   {
    $el->[3]={ defined $el->[3] ? %{$el->[3]} : (), (defined $rextra && ref $rextra eq 'HASH')? %$rextra : () };
   }
   last;
  }
 } else
 {
  push @{$self->{list}},[$name,_remove_dups_ip(\@ipv4),_remove_dups_ip(\@ipv6),$rextra];
 }
}

sub _remove_dups_ip
{
 my $ip=shift;
 my @a;
 my %tmp;
 @a=ref($ip)? grep { ! $tmp{$_}++ } @$ip : ($ip) if defined $ip;
 return \@a;
}

## Give back an array of all hostnames, or up to a limit if provided
sub get_names
{
 my ($self,$limit)=@_;
 return unless (defined $self && ref $self);
 my $c=$self->count();
 $c=$limit if ($limit && ($limit <= $c));
 my @r;
 foreach (0..($c-1))
 {
  push @r,$self->{list}->[$_]->[0];
 }
 return @r;
}

sub count
{
 my $self=shift;
 return unless (defined $self && ref $self);
 return scalar(@{$self->{list}});
}

sub is_empty
{
 my $self=shift;
 my $c=$self->count();
 return (defined $c && ($c > 0))? 0 : 1;
}

sub get_details
{
 my ($self,$pos)=@_;
 return unless (defined $self && ref $self && defined $pos && $pos);
 my $c=$self->count();

 if ($pos=~m/^\d+$/)
 {
  return unless ($c && ($pos <= $c));
  my $el=$self->{list}->[$pos-1];
  return wantarray()? @$el : $el->[0];
 } else
 {
  $pos=lc($pos);
  foreach my $el (@{$self->{list}})
  {
   next unless ($el->[0] eq $pos);
   return wantarray()? @$el : $el->[0];
  }
  return;
 }
}

# Do not use this method for anything else than debugging. The output format is not guaranteed to remain stable
sub as_string
{
 my ($self)=shift;
 my @s;
 foreach my $el (@{$self->{list}})
 {
  my $s=$el->[0];
  my $ips=join(',',@{$el->[1]},@{$el->[2]});
  $s.=' ['.$ips.']' if $ips;
  $s.=' {'.join(' ',map { $_.'='.$el->[3]->{$_} } keys(%{$el->[3]})).'}' if (defined $el->[3] && %{$el->[3]});
  push @s,$s;
 }
 return join(' ',@s);
}

####################################################################################################
1;