The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
Changes 033
MANIFEST 050
META.json 53
META.yml 43
Makefile.PL 11
README.md 042
TODO 05
bin/awhois.pl 0150
lib/Net/Whois/Generic.pm 0702
lib/Net/Whois/Object/AsBlock/AFRINIC.pm 0181
lib/Net/Whois/Object/AsBlock/APNIC.pm 0184
lib/Net/Whois/Object/AsSet/AFRINIC.pm 0206
lib/Net/Whois/Object/AsSet/APNIC.pm 0212
lib/Net/Whois/Object/AsSet.pm 11
lib/Net/Whois/Object/AutNum/AFRINIC.pm 0259
lib/Net/Whois/Object/AutNum/APNIC.pm 0263
lib/Net/Whois/Object/AutNum.pm 33
lib/Net/Whois/Object/Domain/AFRINIC.pm 0236
lib/Net/Whois/Object/Domain/APNIC.pm 0238
lib/Net/Whois/Object/FilterSet/AFRINIC.pm 0211
lib/Net/Whois/Object/FilterSet/APNIC.pm 0214
lib/Net/Whois/Object/Inet6Num/AFRINIC.pm 0263
lib/Net/Whois/Object/Inet6Num/APNIC.pm 0265
lib/Net/Whois/Object/Inet6Num.pm 33
lib/Net/Whois/Object/InetNum/AFRINIC.pm 0264
lib/Net/Whois/Object/InetNum/APNIC.pm 0263
lib/Net/Whois/Object/InetNum.pm 11
lib/Net/Whois/Object/InetRtr/AFRINIC.pm 0226
lib/Net/Whois/Object/Information/AFRINIC.pm 051
lib/Net/Whois/Object/Irt/AFRINIC.pm 0261
lib/Net/Whois/Object/Irt/APNIC.pm 0261
lib/Net/Whois/Object/KeyCert/AFRINIC.pm 0205
lib/Net/Whois/Object/KeyCert/APNIC.pm 0208
lib/Net/Whois/Object/Limerick/AFRINIC.pm 0114
lib/Net/Whois/Object/Limerick.pm 11
lib/Net/Whois/Object/Mntner/AFRINIC.pm 0237
lib/Net/Whois/Object/Mntner/APNIC.pm 0242
lib/Net/Whois/Object/Organisation/AFRINIC.pm 0191
lib/Net/Whois/Object/Organisation/APNIC.pm 0194
lib/Net/Whois/Object/Organisation.pm 716
lib/Net/Whois/Object/PeeringSet/AFRINIC.pm 0143
lib/Net/Whois/Object/PeeringSet/APNIC.pm 0147
lib/Net/Whois/Object/PeeringSet.pm 11
lib/Net/Whois/Object/Person/AFRINIC.pm 0141
lib/Net/Whois/Object/Person/APNIC.pm 0145
lib/Net/Whois/Object/Person.pm 11
lib/Net/Whois/Object/Poem/APNIC.pm 0121
lib/Net/Whois/Object/Poem.pm 44
lib/Net/Whois/Object/PoeticForm/APNIC.pm 0100
lib/Net/Whois/Object/Role/AFRINIC.pm 0160
lib/Net/Whois/Object/Role/APNIC.pm 0163
lib/Net/Whois/Object/Route/AFRINIC.pm 0220
lib/Net/Whois/Object/Route/APNIC.pm 0224
lib/Net/Whois/Object/Route.pm 11
lib/Net/Whois/Object/Route6/AFRINIC.pm 0206
lib/Net/Whois/Object/Route6/APNIC.pm 0210
lib/Net/Whois/Object/RouteSet/AFRINIC.pm 0152
lib/Net/Whois/Object/RouteSet/APNIC.pm 0155
lib/Net/Whois/Object/RouteSet.pm 11
lib/Net/Whois/Object/RtrSet/AFRINIC.pm 0154
lib/Net/Whois/Object/RtrSet/APNIC.pm 0157
lib/Net/Whois/Object/RtrSet.pm 11
lib/Net/Whois/Object.pm 70207
lib/Net/Whois/RIPE.pm 5255
t/00-changes.t 04
t/02-methods.t 89
t/03-objects.t 1148
t/04-generic.t 089
t/105-AsBlock.t 10
t/110-AutNum.t 16
t/115-Person.t 10
t/120-Role.t 10
t/125-AsSet.t 10
t/130-Domain.t 10
t/135-InetNum.t 10
t/140-Inet6Num.t 54
t/145-InetRtr.t 10
t/150-RtrSet.t 10
t/155-Mntner.t 10
t/160-KeyCert.t 10
t/165-Route.t 10
t/167-Route6.t 10
t/170-RouteSet.t 10
t/175-PeeringSet.t 10
t/180-Limerick.t 10
t/185-Poem.t 10
t/187-PoeticForm.t 10
t/190-Organisation.t 28
t/195-Response.t 10
t/200-Information.t 10
t/205-Irt.t 54
t/210-FilterSet.t 10
t/215-SyncUpdates.t 44
t/216-SyncUpdates-Signed.t 085
t/300-AFRINIC.t 024
t/305-APNIC.t 023
t/common.pl 30
97 files changed (This is a version diff) 2169640
@@ -1,5 +1,38 @@
 Revision history for net-whois-ripe
 
+            
+2.005001    2013-10-11
+            - Add support for APNIC objects through Net::Whois::Generic
+            - Simplify query options handling in Net::Whois::Generic
+              (remove keepalive options)
+            - Start adding some documentation (far from enough although)
+
+2.005000    2013-10-10
+            - Add support for generic objects (from various sources, AFRINIC being the first implemented)
+              through Net::Whois::Generic
+
+2.004002    2013-07-31
+            - Add 'abuse_c' to AutNum object
+              (https://www.ripe.net/ripe/docs/ripe-563)
+
+2.004001    2013-06-19
+            - Remove Test::Exception requirement
+            - Add one test
+
+2.004000    2013-05-29
+            - Fix 'delete' mode on accessor
+            - Add awhois.pl skeleton script
+
+2.003000    2013-04-17
+            Another contribution from Moritz Lenz :
+            - Add abuse_c field to Organisation
+            - Inet6num has an attribute 'assignment_size'
+            - Unknown attributes in Object->new do not die anymore
+
+2.002000    2012-12-03
+            - Add 'delete' mode to attribute update
+            - Minor documentation fix
+
 2.001000    2012-11-22
             - Add the clone() method to Net::Whois::Object
             - Enhance accessor for multiple value attributes
@@ -1,39 +1,85 @@
+bin/awhois.pl
 Changes
+lib/Net/Whois/Generic.pm
 lib/Net/Whois/Object.pm
 lib/Net/Whois/Object/AsBlock.pm
+lib/Net/Whois/Object/AsBlock/AFRINIC.pm
+lib/Net/Whois/Object/AsBlock/APNIC.pm
 lib/Net/Whois/Object/AsSet.pm
+lib/Net/Whois/Object/AsSet/AFRINIC.pm
+lib/Net/Whois/Object/AsSet/APNIC.pm
 lib/Net/Whois/Object/AutNum.pm
+lib/Net/Whois/Object/AutNum/AFRINIC.pm
+lib/Net/Whois/Object/AutNum/APNIC.pm
 lib/Net/Whois/Object/Domain.pm
+lib/Net/Whois/Object/Domain/AFRINIC.pm
+lib/Net/Whois/Object/Domain/APNIC.pm
 lib/Net/Whois/Object/FilterSet.pm
+lib/Net/Whois/Object/FilterSet/AFRINIC.pm
+lib/Net/Whois/Object/FilterSet/APNIC.pm
 lib/Net/Whois/Object/Inet6Num.pm
+lib/Net/Whois/Object/Inet6Num/AFRINIC.pm
+lib/Net/Whois/Object/Inet6Num/APNIC.pm
 lib/Net/Whois/Object/InetNum.pm
+lib/Net/Whois/Object/InetNum/AFRINIC.pm
+lib/Net/Whois/Object/InetNum/APNIC.pm
 lib/Net/Whois/Object/InetRtr.pm
+lib/Net/Whois/Object/InetRtr/AFRINIC.pm
 lib/Net/Whois/Object/Information.pm
+lib/Net/Whois/Object/Information/AFRINIC.pm
 lib/Net/Whois/Object/Irt.pm
+lib/Net/Whois/Object/Irt/AFRINIC.pm
+lib/Net/Whois/Object/Irt/APNIC.pm
 lib/Net/Whois/Object/KeyCert.pm
+lib/Net/Whois/Object/KeyCert/AFRINIC.pm
+lib/Net/Whois/Object/KeyCert/APNIC.pm
 lib/Net/Whois/Object/Limerick.pm
+lib/Net/Whois/Object/Limerick/AFRINIC.pm
 lib/Net/Whois/Object/Mntner.pm
+lib/Net/Whois/Object/Mntner/AFRINIC.pm
+lib/Net/Whois/Object/Mntner/APNIC.pm
 lib/Net/Whois/Object/Organisation.pm
+lib/Net/Whois/Object/Organisation/AFRINIC.pm
+lib/Net/Whois/Object/Organisation/APNIC.pm
 lib/Net/Whois/Object/PeeringSet.pm
+lib/Net/Whois/Object/PeeringSet/AFRINIC.pm
+lib/Net/Whois/Object/PeeringSet/APNIC.pm
 lib/Net/Whois/Object/Person.pm
+lib/Net/Whois/Object/Person/AFRINIC.pm
+lib/Net/Whois/Object/Person/APNIC.pm
 lib/Net/Whois/Object/Poem.pm
+lib/Net/Whois/Object/Poem/APNIC.pm
 lib/Net/Whois/Object/PoeticForm.pm
+lib/Net/Whois/Object/PoeticForm/APNIC.pm
 lib/Net/Whois/Object/Response.pm
 lib/Net/Whois/Object/Role.pm
+lib/Net/Whois/Object/Role/AFRINIC.pm
+lib/Net/Whois/Object/Role/APNIC.pm
 lib/Net/Whois/Object/Route.pm
+lib/Net/Whois/Object/Route/AFRINIC.pm
+lib/Net/Whois/Object/Route/APNIC.pm
 lib/Net/Whois/Object/Route6.pm
+lib/Net/Whois/Object/Route6/AFRINIC.pm
+lib/Net/Whois/Object/Route6/APNIC.pm
 lib/Net/Whois/Object/RouteSet.pm
+lib/Net/Whois/Object/RouteSet/AFRINIC.pm
+lib/Net/Whois/Object/RouteSet/APNIC.pm
 lib/Net/Whois/Object/RtrSet.pm
+lib/Net/Whois/Object/RtrSet/AFRINIC.pm
+lib/Net/Whois/Object/RtrSet/APNIC.pm
 lib/Net/Whois/RIPE.pm
 Makefile.PL
 MANIFEST
 META.json			Module JSON meta-data (added by MakeMaker)
 META.yml			Module meta-data (added by MakeMaker)
 README
+README.md
+t/00-changes.t
 t/00-load.t
 t/01-instantiation.t
 t/02-methods.t
 t/03-objects.t
+t/04-generic.t
 t/105-AsBlock.t
 t/110-AutNum.t
 t/115-Person.t
@@ -59,7 +105,11 @@ t/200-Information.t
 t/205-Irt.t
 t/210-FilterSet.t
 t/215-SyncUpdates.t
+t/216-SyncUpdates-Signed.t
+t/300-AFRINIC.t
+t/305-APNIC.t
 t/boilerplate.t
 t/common.pl
 t/pod-coverage.t
 t/pod.t
+TODO
@@ -4,7 +4,7 @@
       "Luis Motta Campos <lmc@cpan.org>"
    ],
    "dynamic_config" : 1,
-   "generated_by" : "ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921",
+   "generated_by" : "ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.131560",
    "license" : [
       "unknown"
    ],
@@ -21,9 +21,7 @@
    },
    "prereqs" : {
       "build" : {
-         "requires" : {
-            "Test::Exception" : "0"
-         }
+         "requires" : {}
       },
       "configure" : {
          "requires" : {
@@ -50,5 +48,5 @@
          "url" : "https://github.com/arhuman/Net-Whois-RIPE"
       }
    },
-   "version" : "2.001"
+   "version" : "2.005001"
 }
@@ -2,12 +2,11 @@
 abstract: 'a pure-Perl implementation of the RIPE Database client.'
 author:
   - 'Luis Motta Campos <lmc@cpan.org>'
-build_requires:
-  Test::Exception: 0
+build_requires: {}
 configure_requires:
   ExtUtils::MakeMaker: 0
 dynamic_config: 1
-generated_by: 'ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120921'
+generated_by: 'ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.131560'
 license: unknown
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -26,4 +25,4 @@ requires:
 resources:
   bugtracker: https://github.com/arhuman/Net-Whois-RIPE/issues
   repository: https://github.com/arhuman/Net-Whois-RIPE
-version: 2.001
+version: 2.005001
@@ -22,7 +22,7 @@ WriteMakefile(
                         bugtracker => 'https://github.com/arhuman/Net-Whois-RIPE/issues'
         },
     },
-    BUILD_REQUIRES => { 'Test::Exception' => 0, },
+    BUILD_REQUIRES => { },
     dist           => { COMPRESS          => 'gzip -9f', SUFFIX => 'gz', },
     clean          => { FILES             => 'Net-Whois-RIPE-*' },
 );
@@ -0,0 +1,42 @@
+# Net::Whois::RIPE
+
+A pure-perl programming interface to the RIPE Database Whois service.
+
+This is a complete rewrite of the old version of the module Luis Motta Campos inherited from
+Paul Gampe. 
+
+This repository (try to) follow the git-flow development model, so please use the 'develop' branch
+for your work/pull request.
+
+## INSTALLATION
+
+To install this module, run the following commands:
+
+	perl Makefile.PL
+	make
+	make test
+	make install
+
+## SUPPORT AND DOCUMENTATION
+
+After installing, you can find documentation for this module with the
+perldoc command.
+
+    perldoc Net::Whois::RIPE
+
+You can also look for information at:
+
+    GitHub.
+        https://github.com/arhuman/Net-Whois-RIPE
+
+
+    Search CPAN
+        http://search.cpan.org/dist/net-whois-ripe
+
+## COPYRIGHT AND LICENCE
+
+Copyright (C) 2010 Luis Motta Campos
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
@@ -0,0 +1,5 @@
+* check abuse-c/abuse-mailbox status 
+* add option to query to get unfiltered data (-B on RIPE) and check for mail on aassad-ripe
+ (make it default ?)
+* change hardcoded options on query to non RIPE sources (use RIPE model)
+* Add more usage examples
@@ -0,0 +1,150 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Net::Whois::Object;
+use Data::Dumper;
+
+####################################################################################
+#
+# Global variables
+
+my $DEBUG;
+my @EXCLUDES;
+my $HELP;
+my $KEY;
+my $ONLY;
+my $QUERY;
+my %QUERY_OPTIONS;
+my @TYPES;
+my $VERSION;
+
+####################################################################################
+#
+# Processing
+
+# Get options value from command line
+GetOptions( 'debug'      => \$DEBUG,
+            'excludes=s' => \@EXCLUDES,
+            'help'       => \$HELP,
+            'key=s'      => \$KEY,
+            'only=s'     => \$ONLY,
+            'query=s'    => \$QUERY,
+            'type=s'     => \@TYPES,
+            'version'    => \$VERSION,
+) or die usage();
+
+if ($HELP) {
+    print usage();
+    exit 0;
+}
+
+if ($VERSION) {
+    print "$0  -  using Net::Whois::RIPE $Net::Whois::RIPE::VERSION\n";
+    exit 0;
+}
+
+# Query can be implicit or explicit
+$QUERY = $ARGV[0] unless $QUERY;
+
+# You can now do
+if (@TYPES) {
+    my $query_types = lc join '|', @TYPES;
+    $query_types =~ s/-//g;
+    $QUERY_OPTIONS{type} = $query_types;
+}
+
+if ($KEY) {
+    $QUERY = "-i $KEY " . $ARGV[0] unless $QUERY =~ /-i/;
+}
+
+if ($DEBUG) {
+    print "QUERY=($QUERY)";
+    print "OTIONS=", Dumper \%QUERY_OPTIONS;
+}
+
+my @objects = Net::Whois::Object->query( $QUERY, \%QUERY_OPTIONS );
+
+# And manipulate the object the OO ways
+for my $object (@objects) {
+    print $object->dump;
+    print $/;
+}
+
+exit 0;
+
+sub excluded {
+    my $tested = shift;
+
+    return 0 unless @EXCLUDES;
+
+    if ($ONLY) {
+        return 1 unless $tested =~ /$ONLY/msi;
+    }
+
+    for my $ex_pattern (@EXCLUDES) {
+        return 1 if $tested =~ /$ex_pattern/msi;
+    }
+
+    return 0;
+}
+
+sub usage {
+
+    return <<EOT;
+
+NAME
+
+    $0 - WHOIS client for RIPE database
+
+SYNOPSIS
+
+    $0 [options] [query ...]
+
+    # Get objects whose maintener is MNT-JAGN
+    $0 --key mnt-by MNT-JAGN
+
+    # Get objects about ASN 30781
+    $0 AS30781
+
+
+OPTIONS
+
+
+--help
+
+    Print a brief help message and exits.
+
+--debug
+
+    Display debugging information
+
+--exclude
+
+    Not yet implemented
+
+--key
+
+    The attribute to be used as the key for the search
+
+--only
+
+    Not yet implemented
+
+--type
+
+    The type of record to be returned (example: person, role, inetnum, route...)
+
+--version
+
+    Display version information
+
+
+DESCRIPTION
+
+This program is a WHOIS client requesting the RIPE database
+
+EOT
+}
+
@@ -0,0 +1,702 @@
+package Net::Whois::Generic;
+
+use 5.006;
+use warnings;
+use strict;
+use IO::Socket::INET;
+use IO::Select;
+use Iterator;
+use Net::Whois::Object;
+use Data::Dumper;
+
+use constant {
+	SOON                    => 30,
+	END_OF_OBJECT_MARK      => "\n\n",
+	EOL                     => "\015\012",
+	QUERY_LIST_OBJECTS      => q{-qtypes },
+};
+
+# simplify if all servers happen to accept same options
+our %RIR = (
+	apnic   => { SERVER => 'whois.apnic.net',   QUERY_NON_RECURSIVE =>  q{-r }, QUERY_REFERRAL => q{-R }, QUERY_UNFILTERED => q{-B },},
+	ripe    => { SERVER => 'whois.ripe.net',    QUERY_NON_RECURSIVE =>  q{-r }, QUERY_REFERRAL => q{-R }, QUERY_UNFILTERED => q{-B },},
+	arin    => { SERVER => 'whois.arin.net',    QUERY_NON_RECURSIVE =>  q{-r }, QUERY_REFERRAL => q{-R }, QUERY_UNFILTERED => q{-B },},
+	lacnic  => { SERVER => 'whois.lacnic.net',  QUERY_NON_RECURSIVE =>  q{-r }, QUERY_REFERRAL => q{-R }, QUERY_UNFILTERED => q{-B },},
+	afrinic => { SERVER => 'whois.afrinic.net', QUERY_NON_RECURSIVE =>  q{-r }, QUERY_REFERRAL => q{-R }, QUERY_UNFILTERED => q{-B },},
+);
+
+=head1 NAME
+
+Net::Whois::Generic - a pure-Perl implementation of a multi source Whois client.
+
+=head1 SYNOPSIS
+
+Net::Whois::Generic is my first attempt to unify Whois information from different sources.
+Historically Net::Whois::RIPE was the first written, then Net::Whois::Object was added to provide
+a RPSL encapsultation of the data returned from RIPE database, with an API more object oriented.
+
+Net::Whois::Generic is a new interface designed to be more generic and to encapsulate data from 
+various sources (RIPE, but also AFRINIC, APNIC...)
+The current implementation is barely a proof of concept, AFRINIC and APNIC are the only other sources implemented,
+but I expect to turn it into a generic/robust implementation based on the users feedback.
+
+Usage is very similar to the Net::Whois::Object :
+
+    my $c = Net::Whois::Generic->new( disconnected => 1, unfiltered => 1 );
+
+    my ($org) = $c->query( 'ORG-AFNC1-AFRINIC', { type => 'organisation' } );
+    # $org is a 'Net::Whois::Object::Organisation::AFRINIC' object;
+    
+    
+    my @o = $c->query('101.0.0.0/8');
+    # @o contains various Net::Whois::Object:Inetnum::APNIC, and Net::Whois::Object::Information objects
+
+As Net::Whois::Generic started as an improvment of Net::Whois::RIPE, and have a good amount of code in common,
+for this reason (and some others) it is currently bundled inside the the Net::Whois::RIPE package.
+This might change in the future although.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor. Returns a new L<Net::Whois::Generic> object with an open connection
+to the RIPE Database service of choice (defaulting to C<whois.ripe.net:43>).
+
+The C<%options> hash migth contain configuration options for the RIPE Database
+server. Not all options provided by the RIPE Database server are suitable for
+this implementation, but the idea is to provide everything someone can show a
+use for. The options currently recognized are:
+
+=over 4
+
+=item B<hostname>  (IPv4 address or DNS name. Default is C<whois.ripe.net>)
+
+The hostname or IP address of the service to connect to
+
+=item B<port> (integer, default is C<43>)
+
+The TCP port of the service to connect to
+
+=item B<timeout> (integer, default is C<5>)
+
+The time-out (in seconds) for the TCP connection.
+
+=item B<referral> (boolean, default is C<false>)
+
+When true, prevents the server from using the referral mechanism for domain
+lookups, so that the RIPE Database server returns an object in the RIPE
+Database with the exact match with the lookup argument, rather than doing a
+referral lookup.
+
+=item B<recursive> (boolean, default is C<false>)
+
+When set to C<true>, prevents recursion into queried objects for personal
+information. This prevents lots of unsolicited objects from showing up on
+queries.
+
+=item B<grouping> (boolean, default is C<false>)
+
+When C<true> enables object grouping in server responses. There's little
+utility to enable this option, as the objects will be parsed and returned on a
+much reasonable format most of the time. For the brave or more knowledgeable
+people that want to have they answers in plain text, this can help stablishing
+a 'good' ordering for the RPSL objects returned by a query ('good' is RIPE
+NCC's definition of 'good' in this case).
+
+=item B<unfiltered> (boolean, default is C<false>)
+
+When C<true> enables unfiltered object output responses. This produces objects
+that can be presented back to the RIPE Database for updating.
+
+=item B<types> (list of valid RIPE Database object types, default is empty, meaning all types)
+
+Restrict the RPSL object types allowed in the response to those in the list.
+Using this option will cause the L<Net::Whois::Generic> object to query the RIPE
+Database for the available object types for validating the list. The response
+will be cached for speed and bandwidth.
+
+=item B<disconnected> (boolean, default is C<false>)
+
+Prevents the constructor from automatically opening a connection to the service
+specified (conneting the socket is the default behavior). When set (C<true>),
+the programmer is responsible for calling C<connect> in order to stablish a
+connection to the RIPE Database service desired.
+
+=back
+
+=cut
+
+{
+	my %default_options = (
+		hostname     => 'whois.ripe.net',
+		port         => '43',
+		timeout      => 5,
+		referral     => 0,
+		recursive    => 0,
+		grouping     => 1,
+		unfiltered   => 0,
+		types        => undef,
+		disconnected => 0,
+	);
+
+	sub new
+	{
+		my ($class, %options) = @_;
+		my %known_options;
+		$known_options{$_} = exists $options{$_} ? $options{$_} : $default_options{$_} foreach keys %default_options;
+
+		my $self = bless { __options => \%known_options }, $class;
+
+		return $self;
+	}
+}
+
+=head2 B<hostname( [$hostname] )>
+
+Accessor to the hostname. Accepts an optional hostname, always return the
+current hostname.
+
+=cut
+
+sub hostname
+{
+	my ($self, $hostname) = @_;
+	$self->{__options}{hostname} = $hostname if defined $hostname;
+	return $self->{__options}{hostname};
+}
+
+=head2 B<port()>
+
+Accessor to the port. Accepts an optional port, always return the current
+port.
+
+=cut
+
+sub port
+{
+	my ($self, $port) = @_;
+	$self->{__options}{port} = $port if defined $port && $port =~ m{^\d+$};
+	return $self->{__options}{port};
+}
+
+=head2 B<timeout()>
+
+Accessor to the timeout configuration option. Accepts an optional timeout,
+always return the current timeout.
+
+=cut
+
+sub timeout
+{
+	my ($self, $timeout) = @_;
+	$self->{__options}{timeout} = $timeout
+		if defined $timeout && $timeout =~ m{^\d+$};
+	return $self->{__options}{timeout};
+}
+
+=begin UNDOCUMENTED
+
+=head2 B<__boolean_accessor( $self, $attribute [, $value ] )>
+
+Private method. Shouldn't be used from other modules.
+
+Generic implementation of an accessor for booleans. Receives a reference to the
+current instance, the attribute name, and a value to be interpreted under
+Perl's boolean rules. Sets or gets the named attribute with the given value.
+Always returns the most up-to-date value of the attribute.
+
+=end UNDOCUMENTED
+
+=cut
+
+sub __boolean_accessor
+{
+	my ($self, $attribute) = (shift, shift);
+	if (scalar @_ == 1) {
+		my $value = shift;
+		$self->{__options}{$attribute} = $value ? 1 : 0;
+	}
+	return $self->{__options}{$attribute};
+}
+
+=head2 B<referral()>
+
+Accessor to the referral configuration option. Accepts an optional referral,
+always return the current referral.
+
+=cut
+
+sub referral
+{
+	my $self = shift;
+	return $self->__boolean_accessor('referral', @_);
+}
+
+=head2 B<recursive()>
+
+Accessor to the recursive configuration option. Accepts an optional recursive,
+always return the current recursive.
+
+=cut
+
+sub recursive
+{
+	my $self = shift;
+	return $self->__boolean_accessor('recursive', @_);
+}
+
+=head2 B<grouping()>
+
+Accessor to the grouping configuration option. Accepts an optional grouping,
+always return the current grouping.
+
+=cut
+
+sub grouping
+{
+	my $self = shift;
+	return $self->__boolean_accessor('grouping', @_);
+}
+
+=head2 B<unfiltered()>
+
+Accessor to the unfiltered configuration option.
+
+=cut
+
+sub unfiltered
+{
+	my $self = shift;
+	return $self->__boolean_accessor('unfiltered', @_);
+}
+
+=head2 B<connect()>
+
+Initiates a connection with the current object's configuration.
+
+=cut
+
+sub connect
+{
+	my $self       = shift;
+	my %connection = (
+		Proto      => 'tcp',
+		Type       => SOCK_STREAM,
+		PeerAddr   => $self->hostname,
+		PeerPort   => $self->port,
+		Timeout    => $self->timeout,
+		Domain     => AF_INET,
+		Multihomed => 1,
+	);
+
+	# Create a new IO::Socket object
+	my $socket = $self->{__state}{socket} = IO::Socket::INET->new(%connection);
+	die q{Can't connect to "} . $self->hostname . ':' . $self->port . qq{". Reason: [$@].\n}
+		unless defined $socket;
+
+	# Register $socket with the IO::Select object
+	if (my $ios = $self->ios) {
+		$ios->add($socket) unless $ios->exists($socket);
+	}
+	else {
+		$self->{__state}{ioselect} = IO::Select->new($socket);
+	}
+}
+
+=head2 B<ios()>
+
+Accessor to the L<IO::Select> object coordinating the I/O to the L<IO::Socket>
+object used by this module to communicate with the RIPE Database Server. You
+shouldn't use this object, but the L</"send()"> and L<"query( $query_string )">
+methods instead.
+
+=cut
+
+sub ios { return $_[0]->{__state}{ioselect} }
+
+=head2 B<socket()>
+
+Read-only accessor to the L<IO::Socket> object used by this module.
+
+=cut
+
+sub socket { return $_[0]->{__state}{socket} }
+
+=head2 B<send()>
+
+Sends a message to the RIPE Database server instance to which we're connected
+to. Dies if it cannot write, or if there's no open connection to the server.
+
+Return C<true> if the message could be written to the socket, C<false>
+otherwise.
+
+=cut
+
+sub send
+{
+	my ($self, $message) = @_;
+	die q{Not connected} unless $self->is_connected;
+	if ($self->ios->can_write(SOON + $self->timeout)) {
+		$self->socket->print($message, EOL);
+		$self->socket->flush;
+		return 1;
+	}
+	return 0;
+}
+
+=head2 B<reconnect()>
+
+Reconnects to the server in case we lost connection.
+
+=cut
+
+sub reconnect
+{
+	my $self = shift;
+	$self->disconnect if $self->is_connected;
+	$self->connect;
+}
+
+=head2 B<disconnect()>
+
+Disconnects this client from the server. This renders the client useless until
+you call L</"connect()"> again. This method is called by L</DESTROY()> as part of
+an object's clean-up process.
+
+=cut
+
+sub disconnect
+{
+	my $self = shift;
+	if ($self->is_connected) {
+		my $socket = $self->{__state}{socket};
+		$socket->close;
+		$self->{__state}{ioselect}->remove($socket)
+			if $self->{__state}{ioselect};
+		delete $self->{__state}{socket};
+	}
+}
+
+=head2 B<is_connected()>
+
+Returns C<true> if this instance is connected to the RIPE Database service
+configured.
+
+=cut
+
+sub is_connected
+{
+	my $self   = shift;
+	my $socket = $self->socket;
+	return UNIVERSAL::isa($socket, 'IO::Socket')
+		&& $socket->connected ? 1 : 0;
+}
+
+=head2 B<DESTROY()>
+
+Net::Whois::Generic object destructor. Called by the Perl interpreter upon
+destruction of an instance.
+
+=cut
+
+sub DESTROY
+{
+	my $self = shift;
+	$self->disconnect;
+}
+
+=head2 B<_find_rir( $query_string )>
+
+Guess the associated RIR based on the query.
+
+=cut
+
+sub _find_rir
+{
+	my ($self, $query) = @_;
+
+	my $rir;
+
+	if (       ($query =~ /^(41|102|105|154|196|197)\.\d+\.\d+\.\d+/)
+		or ($query =~ /AFRINIC/i)
+		or ($query =~ /^2c00::/i))
+	{
+		$rir = 'afrinic';
+	}
+	elsif (    (          $query =~ /^(23|34|50|64|64|65|66|67|68|69|70|71|72|73|74|75|76|96|97|98|9|100|104|107|108|135|136|142|147|162|166|172|173|174|184|192|198|199|204|205|206|207|208|209|216)/
+			or ($query =~ /^(2001:0400|2001:1800|2001:4800:|2600|2610:0000):/i)
+			or $query =~ /ARIN/
+		)
+		)
+	{
+		$rir = 'arin';
+
+	}
+	elsif (    (          $query =~ /^(10|14|27|36|39|42|49|58|59|60|61|101|103|106|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|169\.208|175|180|182|183|202|203|210|211|218|219|220|221|222|223)\.\d+\.\d+/
+			or ($query =~ /^(2001:0200|2001:0C00|2001:0E00|2001:4400|2001:8000|2001:A000|2001:B000|2400:0000|2001:0DC0|2001:0DE8|2001:0DF0|2001:07FA|2001:0DE0|2001:0DB8):/i)
+			or $query =~ /APNIC/
+		)
+		)
+	{
+		$rir = 'apnic';
+
+	}
+	else {
+		$rir = 'ripe';
+	}
+
+	return $rir;
+}
+
+=head2 B<adapt_query( $query_string[, $rir] )>
+
+Adapt a query to set various parameter (whois server, query options...) based on the query.
+Takes an optional parameter $rir, to force a specific RIR to be used.
+
+=cut
+
+sub adapt_query
+{
+	my ($self, $query, $rir) = @_;
+	my $fullquery;
+
+	# determine RIR unless $rir;
+	$rir = $self->_find_rir($query) unless $rir;
+
+	if ($rir eq 'ripe') {
+		$self->hostname($RIR{ripe}{SERVER});
+	}
+	elsif ($rir eq 'afrinic') {
+		$fullquery = '-V Md5.0 ' . $query;
+		$self->hostname($RIR{afrinic}{SERVER});
+	}
+	elsif ($rir eq 'arin') {
+		$self->hostname($RIR{arin}{SERVER});
+	}
+	elsif ($rir eq 'lacnic') {
+		$self->hostname($RIR{lacnic}{SERVER});
+	}
+	elsif ($rir eq 'apnic') {
+		$self->hostname($RIR{apnic}{SERVER});
+	}
+
+    my $parameters = "";
+    $parameters .= q{ } . $RIR{$rir}{QUERY_UNFILTERED} if $self->unfiltered;
+    $parameters .= q{ } . $RIR{$rir}{QUERY_NON_RECURSIVE} unless $self->recursive;
+    $parameters .= q{ } . $RIR{$rir}{QUERY_REFERRAL} if $self->referral;
+    $fullquery = $parameters . $query;
+
+	return $fullquery;
+}
+
+=head2 B<query( $query_string )>
+
+Sends a query to the server. Returns an L<Iterator> object that will return one RPSL block at a time.
+
+=cut
+
+sub query
+{
+	my ($self, $query, $options) = @_;
+
+	my $attribute;
+	my $type;
+	my $response;
+
+	for my $opt (keys %$options) {
+		if ($opt =~ /^attribute$/i) {
+			$attribute = $options->{$opt};
+		}
+		elsif ($opt =~ /^type$/i) {
+			$type = $options->{$opt};
+		}
+	}
+
+	$query = $self->adapt_query($query);
+	my $iterator  = $self->__query($query);
+
+	my @objects = Net::Whois::Object->new($iterator);
+
+	($response) = grep { ref($_) =~ /response/i } @objects;
+
+	if ($response) {
+		$self->_process_response($response);
+
+	}
+
+	if ($type) {
+		@objects = grep { ref($_) =~ /$type/i } @objects;
+	}
+
+	if ($attribute) {
+		return grep {defined} map {
+			my $r;
+			eval { $r = $_->$attribute };
+			$@ ? undef : ref($r) eq 'ARRAY' ? @$r : $r
+		} @objects;
+	}
+	else {
+		return grep {defined} @objects;
+	}
+}
+
+# Allows me to pass in queries without having all the automatic options added
+# up to it.
+sub __query
+{
+	my ($self, $query) = @_;
+
+	$self->connect;
+
+	# die "Not connected" unless $self->is_connected;
+
+	if ($self->ios->can_write(SOON + $self->timeout)) {
+		$self->socket->print($query, EOL);
+
+		return Iterator->new(
+			sub {
+				local $/ = END_OF_OBJECT_MARK;
+				if ($self->ios->can_read(SOON + $self->timeout)) {
+					my $block = $self->socket->getline;
+					return $block if defined $block;
+				}
+				Iterator::is_done;
+			}
+		);
+	}
+}
+
+=head2 B<object_types()>
+
+Return a list of known object types from the RIPE Database.
+
+RIPE currently returns 21 types (Limerik have been removed):
+as-block as-set aut-num domain filter-set inet6num inetnum inet-rtr irt
+key-cert mntner organisation peering-set person poem poetic-form role route
+route6 route-set rtr-set
+
+Due to some strange mis-behaviour in the protocol (or documentation?) the RIPE
+Database server won't allow a keep-alive token with this query, meaning the
+connection will be terminated after this query.
+
+=cut
+
+sub object_types
+{
+	my $self     = shift;
+	my $iterator = $self->__query(QUERY_LIST_OBJECTS);
+	while (!$iterator->is_exhausted) {
+		my $value = $iterator->value;
+		return split /\s+/, $value if $value !~ /^%\s/;
+	}
+	return;
+}
+
+=head2 B<_process_response( $response )>
+
+Process a response (error code, error message...)
+
+=cut
+
+sub _process_response
+{
+    my $self = shift;
+	my $response = shift;
+	my $code;
+	my $msg;
+
+    eval { $response->comment };
+    die "Dump : ".Dumper $response    if $@; 
+
+	if ($response->response =~ /ERROR.*:.*?(\d+)/) {
+		$code = $1;
+		$msg = join '', $response->comment();
+	}
+}
+
+=head1 AUTHOR
+
+Arnaud "Arhuman" Assad, C<< <arhuman at gmail.com> >>
+
+=head1 CAVEATS
+
+=over 4
+
+=item B<Update>
+
+Update of objects from database other than RIPE is not currently implemented...
+
+=item B<Sources>
+
+Currently the only sources implemented are RIPE, AFRINIC, and APNIC.
+
+=item B<Maturity>
+
+The Net::Whois::Generic interface is highly experimental.
+There are probably bugs, without any doubt missing documentation and
+examples but please don't hesitate to contact me to suggest corrections
+and improvments.
+
+=back
+
+=head1 BUGS
+
+Please report any bugs or feature requests to C<bug-net-whois-ripe at
+rt.cpan.org>, or through the web interface at
+L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=net-whois-ripe>.  I will be
+notified, and then you'll automatically be notified of progress on your bug as
+I make changes.
+
+=head1 SEE ALSO
+
+There are several tools similar to L<Net::Whois::Generic>, I'll list some of them below and some reasons why Net::Whois::Generic exists anyway:
+
+L<Net::Whois::IANA> - A universal WHOIS extractor: update not possible, no RPSL parser
+
+L<Net::Whois::ARIN> - ARIN whois client: update not possible, only subset of ARIN objects handled
+
+L<Net::Whois::Parser> - Module for parsing whois information: no query handling, parser can (must?) be added
+
+L<Net::Whois::RIPE> - RIPE whois client: the basis for L<Net::Whois::Generic> but only handle RIPE.
+   
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+    perldoc Net::Whois::Generic
+
+You can also look for information at:
+
+=over 4
+
+=item * RT: CPAN's request tracker
+
+L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=net-whois-ripe>
+
+=item * AnnoCPAN: Annotated CPAN documentation
+
+L<http://annocpan.org/dist/net-whois-ripe>
+
+=item * CPAN Ratings
+
+L<http://cpanratings.perl.org/d/net-whois-ripe>
+
+=item * Search CPAN
+
+L<http://search.cpan.org/dist/net-whois-ripe>
+
+=back
+
+
+=head1 ACKNOWLEDGEMENTS
+
+Thanks to Jaguar Networks which grants me time to work on this module.
+
+=head1 COPYRIGHT & LICENSE
+
+Copyright 2013 Arnaud "Arhuman" Assad, all rights reserved.
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
@@ -0,0 +1,181 @@
+package Net::Whois::Object::AsBlock::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t as-block -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# as-block:       [mandatory]  [single]     [primary/look-up key]
+# descr:          [optional]   [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+
+__PACKAGE__->attributes( 'primary', ['as_block'] );
+__PACKAGE__->attributes( 'mandatory', [ 'as_block', 'admin_c', 'tech_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'descr', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single', [ 'as_block', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'remarks', 'org', 'admin_c', 'tech_c', 'notify', 'mnt_lower', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::AsBlock::AFRINIC - an object representation of the RPSL AsBlock block
+
+=head1 DESCRIPTION
+
+An as-block object is needed to delegate a range of AS numbers to a
+given repository.  This object may be used for authorisation of the
+creation of aut-num objects within the range specified by the
+"as-block:" attribute.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::AsBlock::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+}
+
+=head2 B<as_block( [$as_block] )>
+
+Accessor to the as_block attribute.
+Accepts an optional as_block, always return the current as_block value.
+
+An as_block is a range of AS numbers delegated to a Regional or National Internet Registry
+(NIR).
+
+The AS numbers in the range are subsequently assigned by the registry to
+members or end-users in the region.
+Information on individual AS numbers within an as-block object are
+stored in the appropriate Internet Registry's Whois Database.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr, always return the current descr value.
+
+Description of the Internet Registry delegated the range of AS numbers shown
+in the as-block.
+
+=head2 B<remarks( [$remarks] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remarks to be added to the remarks array,
+always return the current remarks array.
+
+Information on the registry that maintains details of AS numbers assigned from
+the as-block.
+
+Also includes where to direct a whois client to find further information on
+the AS numbers.
+
+=head2 B<tech_c( [$tech_c] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional tech_c to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech-c
+listed.
+
+A technical contact (tech-c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+
+=head2 B<admin_c( [$admin_c])>
+
+Accessor to the admin_c attribute.
+Accepts an optional admin_c to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin-c listed.
+
+An administrative contact(admin-c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional value to be added notify array,
+        always return the current notify array.
+
+The email address to which notifications of changes 
+to the object should be sent.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+The identifier of a registered 'mntner' object used to authorize the creation
+of 'aut-num' objects within the range specified by the as-block.
+
+If no 'mnt-lower' is specified, the 'mnt-by' attribute is used for
+authorization.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to this
+object.
+
+When your database details are protected by a 'mntner' object, then
+only persons with access to the security information of that 'mntner'
+object will be able to change details.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+The organisation entity this object is bound to.
+
+=cut
+
+1;
@@ -0,0 +1,184 @@
+package Net::Whois::Object::AsBlock::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t as-block
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# as-block:       [mandatory]  [single]     [primary/lookup key]
+# descr:          [optional]   [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# country:        [optional]   [single]     [ ]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# org:            [optional]   [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+% This query was served by the APNIC Whois Service version 1.68.5 (WHOIS1)
+
+__PACKAGE__->attributes( 'primary', ['as_block'] );
+__PACKAGE__->attributes( 'mandatory', [ 'as_block', 'admin_c', 'tech_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'descr', 'remarks', 'country', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single', [ 'as_block', 'country', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'remarks', 'admin_c', 'tech_c', 'org', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::AsBlock::APNIC - an object representation of the RPSL AsBlock block
+
+=head1 DESCRIPTION
+
+An as-block object is needed to delegate a range of AS numbers to a
+given repository.  This object may be used for authorisation of the
+creation of aut-num objects within the range specified by the
+"as-block:" attribute.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::AsBlock::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+}
+
+=head2 B<as_block( [$as_block] )>
+
+Accessor to the as_block attribute.
+Accepts an optional as_block, always return the current as_block value.
+
+An as_block is a range of AS numbers delegated to a Regional or National Internet Registry
+(NIR).
+
+The AS numbers in the range are subsequently assigned by the registry to
+members or end-users in the region.
+Information on individual AS numbers within an as-block object are
+stored in the appropriate Internet Registry's Whois Database.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr, always return the current descr value.
+
+Description of the Internet Registry delegated the range of AS numbers shown
+in the as-block.
+
+=head2 B<remarks( [$remarks] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remarks to be added to the remarks array,
+always return the current remarks array.
+
+Information on the registry that maintains details of AS numbers assigned from
+the as-block.
+
+Also includes where to direct a whois client to find further information on
+the AS numbers.
+
+=head2 B<tech_c( [$tech_c] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional tech_c to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech-c
+listed.
+
+A technical contact (tech-c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+
+=head2 B<admin_c( [$admin_c])>
+
+Accessor to the admin_c attribute.
+Accepts an optional admin_c to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin-c listed.
+
+An administrative contact(admin-c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional value to be added notify array,
+        always return the current notify array.
+
+The email address to which notifications of changes 
+to the object should be sent.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+The identifier of a registered 'mntner' object used to authorize the creation
+of 'aut-num' objects within the range specified by the as-block.
+
+If no 'mnt-lower' is specified, the 'mnt-by' attribute is used for
+authorization.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to this
+object.
+
+When your database details are protected by a 'mntner' object, then
+only persons with access to the security information of that 'mntner'
+object will be able to change details.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+The organisation entity this object is bound to.
+
+=cut
+
+1;
@@ -0,0 +1,206 @@
+package Net::Whois::Object::AsSet::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t as-block -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# as-block:       [mandatory]  [single]     [primary/look-up key]
+# descr:          [optional]   [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['as_set'] );
+__PACKAGE__->attributes( 'mandatory', [ 'as_set', 'admin_c', 'tech_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'descr', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single', [ 'as_set', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'remarks', 'org', 'admin_c', 'tech_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::AsSet::AFRINIC - an object representation of a RPSL AsSet block
+
+=head1 DESCRIPTION
+
+An as-set object defines a set of aut-num objects. 
+It defines a group of Autonomous Systems with the same routing policies.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::AsSet::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<as_set( [$as_set])>
+
+Accessor to the as_set attribute.
+Accepts an optional as_set, always return the current as_set value.
+
+The as_set attribute defines the name of the set. It is an RPSL name that
+starts with "as-" or as_set names and AS numbers separated by colon (':').
+The later form is called Hierarchical form, the former non-hierarchical.
+There must be at least one set-name within the hierarchical form that starts 
+with 'as-'.
+
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr to be added to the descr array, 
+always return the current descr array.
+
+A short description related to the object's purpose.
+
+=head2 B<members( [$member] )>
+
+Accessor to the members attribute.
+Accepts an optional member to be added to the members array,
+always return the current 'members' array.
+
+The members attribute lists the members of the set. It can be either a list
+of AS Numbers, or other as-set names.
+
+=head2 B<mbrs_by_ref( [$mbr] )>
+
+Accessor to the mbrs_by_ref attribute.
+Accepts an optional mbr to be added to the mbrs_by_ref array,
+always return the current mbrs_by_ref array.
+
+The identifier of a registered 'mntner' object that can be used to add members
+to the as-set indirectly.
+
+The mbrs_by_ref attribute can be used in all "set" objects; it allows
+indirect population of a set. If this attribute is used, the set also includes
+objects of the corresponding type (aut-num objects for as-set, for example)
+that are protected by one of these maintainers and whose "member-of:"
+attributes refer to the name of the set. If the value of a mbrs_by_ref
+attribute is ANY, any object of the corresponding type referring to the set is
+a member of the set. If the mbrs_by_ref attribute is missing, the set is
+defined explicitly by the members attribute.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+Information about the object that cannot be stated in other attributes.
+May include a URL or email address.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<tech_c( [$tech_c] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional tech_c to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech-c
+listed.
+
+A technical contact (tech-c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<admin_c( [$admin_c] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional admin_c to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin-c listed.
+
+An administrative contact (admin-c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object will be
+sent.
+
+=head2 B<mnt_by( [$mnt] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to this
+object.
+
+When your database details are protected by a 'mntner' object, then
+only persons with access to the security information of that 'mntner'
+object will be able to change details.
+
+=head2 B<mnt_lower( [$mnt] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+Specifies the identifier of a registered mntner object used
+for hierarchical authorisation.  Protects creation of objects
+directly (one level) below in the hierarchy of an object type.
+The authentication method of this maintainer object will then
+be used upon creation of any object directly below the object
+that contains the "mnt-lower:" attribute.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -0,0 +1,212 @@
+package Net::Whois::Object::AsSet::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t as-set
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# as-set:         [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# country:        [optional]   [single]     [ ]
+# members:        [optional]   [multiple]   [ ]
+# mbrs-by-ref:    [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS2)
+
+__PACKAGE__->attributes( 'primary', ['as_set'] );
+__PACKAGE__->attributes( 'mandatory', [ 'as_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'country', 'members', 'mbrs_by_ref', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single', [ 'as_set', 'country', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'members', 'mbrs_by_ref', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::AsSet::APNIC - an object representation of a RPSL AsSet block
+
+=head1 DESCRIPTION
+
+An as-set object defines a set of aut-num objects. 
+It defines a group of Autonomous Systems with the same routing policies.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::AsSet::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<as_set( [$as_set])>
+
+Accessor to the as_set attribute.
+Accepts an optional as_set, always return the current as_set value.
+
+The as_set attribute defines the name of the set. It is an RPSL name that
+starts with "as-" or as_set names and AS numbers separated by colon (':').
+The later form is called Hierarchical form, the former non-hierarchical.
+There must be at least one set-name within the hierarchical form that starts 
+with 'as-'.
+
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr to be added to the descr array, 
+always return the current descr array.
+
+A short description related to the object's purpose.
+
+=head2 B<members( [$member] )>
+
+Accessor to the members attribute.
+Accepts an optional member to be added to the members array,
+always return the current 'members' array.
+
+The members attribute lists the members of the set. It can be either a list
+of AS Numbers, or other as-set names.
+
+=head2 B<mbrs_by_ref( [$mbr] )>
+
+Accessor to the mbrs_by_ref attribute.
+Accepts an optional mbr to be added to the mbrs_by_ref array,
+always return the current mbrs_by_ref array.
+
+The identifier of a registered 'mntner' object that can be used to add members
+to the as-set indirectly.
+
+The mbrs_by_ref attribute can be used in all "set" objects; it allows
+indirect population of a set. If this attribute is used, the set also includes
+objects of the corresponding type (aut-num objects for as-set, for example)
+that are protected by one of these maintainers and whose "member-of:"
+attributes refer to the name of the set. If the value of a mbrs_by_ref
+attribute is ANY, any object of the corresponding type referring to the set is
+a member of the set. If the mbrs_by_ref attribute is missing, the set is
+defined explicitly by the members attribute.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+Information about the object that cannot be stated in other attributes.
+May include a URL or email address.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<tech_c( [$tech_c] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional tech_c to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech-c
+listed.
+
+A technical contact (tech-c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<admin_c( [$admin_c] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional admin_c to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin-c listed.
+
+An administrative contact (admin-c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object will be
+sent.
+
+=head2 B<mnt_by( [$mnt] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to this
+object.
+
+When your database details are protected by a 'mntner' object, then
+only persons with access to the security information of that 'mntner'
+object will be able to change details.
+
+=head2 B<mnt_lower( [$mnt] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+Specifies the identifier of a registered mntner object used
+for hierarchical authorisation.  Protects creation of objects
+directly (one level) below in the hierarchy of an object type.
+The authentication method of this maintainer object will then
+be used upon creation of any object directly below the object
+that contains the "mnt-lower:" attribute.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -2,7 +2,7 @@ package Net::Whois::Object::AsSet;
 
 use base qw/Net::Whois::Object/;
 
-# From : whois -t as-set  
+# From: whois -t as-set  
 #
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
@@ -0,0 +1,259 @@
+package Net::Whois::Object::AutNum::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t aut-num -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# aut-num:        [mandatory]  [single]     [primary/look-up key]
+# as-name:        [mandatory]  [single]     [ ]
+# descr:          [mandatory]  [multiple]   [ ]
+# member-of:      [optional]   [multiple]   [ ]
+# import:         [optional]   [multiple]   [ ]
+# mp-import:      [optional]   [multiple]   [ ]
+# export:         [optional]   [multiple]   [ ]
+# mp-export:      [optional]   [multiple]   [ ]
+# default:        [optional]   [multiple]   [ ]
+# mp-default:     [optional]   [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [single]     [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-irt:        [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+
+__PACKAGE__->attributes( 'primary',   ['aut_num'] );
+__PACKAGE__->attributes( 'mandatory', [ 'aut_num', 'as_name', 'descr', 'admin_c', 'tech_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'member_of', 'import', 'mp_import', 'export', 'mp_export', 'default', 'mp_default', 'remarks', 'org', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_irt'  ] );
+__PACKAGE__->attributes( 'single', [ 'aut_num', 'as_name', 'org', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'member_of', 'import', 'mp_import', 'export', 'mp_export', 'default', 'mp_default', 'remarks', 'admin_c', 'tech_c', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_by', 'mnt_irt', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::AutNum::AFRINIC - an object representation of a RPSL AutNum block
+
+=head1 DESCRIPTION
+
+Autonomous System numbers ('aut-num' objects) are globally unique identifiers
+for Autonomous Systems.
+
+The aut-num object specifies routing policies. It refers to a group of IP
+networks that have a single and clearly defined external routing policy,
+operated by one or more network operators – an Autonomous System (AS).
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::AutNum::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<aut_num( [$aut_num] )>
+
+Accessor to the aut_num attribute.
+Accepts an optional aut_num, always return the current aut_num array.
+
+The value of the aut_num attribute is the AS Number of the Autonomous
+System that this object describes and takes the form of ASn where n is 
+a 32 bit number..
+
+Leading zeroes (AS0352) are not allowed and will be removed (AS352) by the
+database software.
+
+=cut
+
+sub aut_num {
+    my ( $self, $aut_num ) = @_;
+
+    if ( $aut_num and $aut_num !~ /^AS\d+/ ) {
+        warn "Illegal aut-num ($aut_num) : should be ASn, n being a 32 bit number with no leading 0";
+    }
+
+    return $self->_single_attribute_setget( 'aut_num', $aut_num );
+}
+
+=head2 B<as_name( [$as_name] )>
+
+Accessor to the as_name attribute.
+Accepts an optional as_name, always return the current as_name array.
+
+The as-name attribute is a symbolic name of the AS.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr value to be added to the descr array, always return the current descr array.
+
+=head2 B<member_of( [$mbr_of] )>
+
+Accessor to the member_of attribute.
+Accepts an optional member_of value to be added to the member_of array,
+always return the current member_of array.
+
+The member_of attribute value identifies a set object that this object
+wants to be a member of. This claim, however, should be acknowledged by a
+respective mbrs_by_ref attribute in the referenced object.
+
+An aut-num may be useful to include in an 'as-set' if your network maintains a
+number of Autonomous Systems or wishes to include its routes in an upstream
+provider's routing information.
+
+To be included in an 'as-set', the 'as-set' object must:
+include the keyword "ANY" or the AS number's mbrs_by_ref attribute
+and/or list the AS number in the members attribute
+
+=head2 B<import( [$import] )>
+
+Accessor to the import attribute.
+Accepts an optional import line to be added to the import array,
+always return the current import array.
+
+The inbound IPv4 routing policy of the AS.
+
+=head2 B<mp_import( [$import] )>
+
+Accessor to the mp_import attribute.
+Accepts an optional mp_import line to be added to the import array,
+always return the current mp_import array.
+
+The inbound IPv6 routing policy of the AS.
+
+=head2 B<export( [$export] )>
+
+Accessor to the export attribute.
+Accepts an optional export line to be added to the export array,
+always return the current export array.
+
+The outbound routing policy of the AS.
+
+=head2 B<mp_export( [$mp_export] )>
+
+Accessor to the mp_export attribute.
+Accepts an optional mp_export line to be added to the mp_export array,
+always return the current mp_export array.
+
+The outbound IPv6 routing policy of the AS.
+
+=head2 B<default( [$default] )>
+
+Accessor to the default attribute.
+Accepts an optional default value to be added to the default array,
+always return the current default array.
+
+The peer network the AS will use for as a default, that is, when the AS has no
+more-specific information on where to send the traffic.
+
+=head2 B<mp_default( [$mp_default] )>
+
+Accessor to the mp_default attribute.
+Accepts an optional mp_default line to be added to the mp_default array,
+always return the current mp_default array.
+
+This attribute performs the same function as the 'default' attribute above.
+The difference is that mp-default allows both IPv4 and IPv6 addresses to be
+specified.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+Information about the object that cannot be stated in other attributes. May
+include a URL or email address.
+
+=cut
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=cut
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=head2 B<mnt_routes( [$mnt_routes] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_routes value to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Only a single value for the org attribute is allowed in the aut-num object.
+This is to ensure only one organisation is responsible for this resource.
+
+=cut
+
+1;
@@ -0,0 +1,263 @@
+package Net::Whois::Object::AutNum::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t aut-num
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# aut-num:        [mandatory]  [single]     [primary/lookup key]
+# as-name:        [mandatory]  [single]     [ ]
+# descr:          [mandatory]  [multiple]   [ ]
+# country:        [mandatory]  [single]     [ ]
+# member-of:      [optional]   [multiple]   [inverse key]
+# import:         [optional]   [multiple]   [ ]
+# mp-import:      [optional]   [multiple]   [ ]
+# export:         [optional]   [multiple]   [ ]
+# mp-export:      [optional]   [multiple]   [ ]
+# default:        [optional]   [multiple]   [ ]
+# mp-default:     [optional]   [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [single]     [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-irt:        [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS4)
+
+
+__PACKAGE__->attributes( 'primary',   ['aut_num'] );
+__PACKAGE__->attributes( 'mandatory', [ 'aut_num', 'as_name', 'descr', 'country', 'admin_c', 'tech_c', 'mnt_by', 'mnt_irt', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'member_of', 'import', 'mp_import', 'export', 'mp_export', 'default', 'mp_default', 'remarks', 'org', 'notify', 'mnt_lower', 'mnt_routes'  ] );
+__PACKAGE__->attributes( 'single', [ 'aut_num', 'as_name', 'country', 'org', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'member_of', 'import', 'mp_import', 'export', 'mp_export', 'default', 'mp_default', 'remarks', 'admin_c', 'tech_c', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_by', 'mnt_irt', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::AutNum::APNIC - an object representation of a RPSL AutNum block
+
+=head1 DESCRIPTION
+
+Autonomous System numbers ('aut-num' objects) are globally unique identifiers
+for Autonomous Systems.
+
+The aut-num object specifies routing policies. It refers to a group of IP
+networks that have a single and clearly defined external routing policy,
+operated by one or more network operators – an Autonomous System (AS).
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::AutNum::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<aut_num( [$aut_num] )>
+
+Accessor to the aut_num attribute.
+Accepts an optional aut_num, always return the current aut_num array.
+
+The value of the aut_num attribute is the AS Number of the Autonomous
+System that this object describes and takes the form of ASn where n is 
+a 32 bit number..
+
+Leading zeroes (AS0352) are not allowed and will be removed (AS352) by the
+database software.
+
+=cut
+
+sub aut_num {
+    my ( $self, $aut_num ) = @_;
+
+    if ( $aut_num and $aut_num !~ /^AS\d+/ ) {
+        warn "Illegal aut-num ($aut_num) : should be ASn, n being a 32 bit number with no leading 0";
+    }
+
+    return $self->_single_attribute_setget( 'aut_num', $aut_num );
+}
+
+=head2 B<as_name( [$as_name] )>
+
+Accessor to the as_name attribute.
+Accepts an optional as_name, always return the current as_name array.
+
+The as-name attribute is a symbolic name of the AS.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr value to be added to the descr array, always return the current descr array.
+
+=head2 B<member_of( [$mbr_of] )>
+
+Accessor to the member_of attribute.
+Accepts an optional member_of value to be added to the member_of array,
+always return the current member_of array.
+
+The member_of attribute value identifies a set object that this object
+wants to be a member of. This claim, however, should be acknowledged by a
+respective mbrs_by_ref attribute in the referenced object.
+
+An aut-num may be useful to include in an 'as-set' if your network maintains a
+number of Autonomous Systems or wishes to include its routes in an upstream
+provider's routing information.
+
+To be included in an 'as-set', the 'as-set' object must:
+include the keyword "ANY" or the AS number's mbrs_by_ref attribute
+and/or list the AS number in the members attribute
+
+=head2 B<import( [$import] )>
+
+Accessor to the import attribute.
+Accepts an optional import line to be added to the import array,
+always return the current import array.
+
+The inbound IPv4 routing policy of the AS.
+
+=head2 B<mp_import( [$import] )>
+
+Accessor to the mp_import attribute.
+Accepts an optional mp_import line to be added to the import array,
+always return the current mp_import array.
+
+The inbound IPv6 routing policy of the AS.
+
+=head2 B<export( [$export] )>
+
+Accessor to the export attribute.
+Accepts an optional export line to be added to the export array,
+always return the current export array.
+
+The outbound routing policy of the AS.
+
+=head2 B<mp_export( [$mp_export] )>
+
+Accessor to the mp_export attribute.
+Accepts an optional mp_export line to be added to the mp_export array,
+always return the current mp_export array.
+
+The outbound IPv6 routing policy of the AS.
+
+=head2 B<default( [$default] )>
+
+Accessor to the default attribute.
+Accepts an optional default value to be added to the default array,
+always return the current default array.
+
+The peer network the AS will use for as a default, that is, when the AS has no
+more-specific information on where to send the traffic.
+
+=head2 B<mp_default( [$mp_default] )>
+
+Accessor to the mp_default attribute.
+Accepts an optional mp_default line to be added to the mp_default array,
+always return the current mp_default array.
+
+This attribute performs the same function as the 'default' attribute above.
+The difference is that mp-default allows both IPv4 and IPv6 addresses to be
+specified.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+Information about the object that cannot be stated in other attributes. May
+include a URL or email address.
+
+=cut
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=cut
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=head2 B<mnt_routes( [$mnt_routes] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_routes value to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Only a single value for the org attribute is allowed in the aut-num object.
+This is to ensure only one organisation is responsible for this resource.
+
+=cut
+
+1;
@@ -2,7 +2,7 @@ package Net::Whois::Object::AutNum;
 
 use base qw/Net::Whois::Object/;
 
-# from : whois -t aut-num
+# from: whois -t aut-num
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
@@ -34,8 +34,8 @@ use base qw/Net::Whois::Object/;
 
 __PACKAGE__->attributes( 'primary',   ['aut_num'] );
 __PACKAGE__->attributes( 'mandatory', [ 'aut_num', 'as_name', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
-__PACKAGE__->attributes( 'optional', [ 'member_of', 'import', 'mp_import', 'export', 'mp_export', 'default', 'mp_default', 'remarks', 'org', 'notify', 'mnt_lower', 'mnt_routes'  ] );
-__PACKAGE__->attributes( 'single', [ 'aut_num', 'as_name', 'org', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'member_of', 'import', 'mp_import', 'export', 'mp_export', 'default', 'mp_default', 'remarks', 'org', 'notify', 'mnt_lower', 'mnt_routes', 'abuse_c'  ] );
+__PACKAGE__->attributes( 'single', [ 'aut_num', 'as_name', 'org', 'source', 'abuse_c' ] );
 __PACKAGE__->attributes( 'multiple', [ 'descr', 'member_of', 'import', 'mp_import', 'export', 'mp_export', 'default', 'mp_default', 'remarks', 'admin_c', 'tech_c', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_by', 'changed' ] );
 
 
@@ -0,0 +1,236 @@
+package Net::Whois::Object::Domain::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t domain -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# domain:         [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# zone-c:         [mandatory]  [multiple]   [inverse key]
+# nserver:        [optional]   [multiple]   [inverse key]
+# ds-rdata:       [optional]   [multiple]   [inverse key]
+# sub-dom:        [optional]   [multiple]   [inverse key]
+# dom-net:        [optional]   [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [optional]   [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# refer:          [optional]   [single]     [ ]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+    
+__PACKAGE__->attributes( 'primary',   ['domain'] );
+__PACKAGE__->attributes( 'mandatory', [ 'domain', 'descr', 'admin_c', 'tech_c', 'zone_c', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'org', 'nserver', 'ds_rdata', 'sub_dom', 'dom_net', 'remarks', 'notify', 'mnt_by', 'mnt_lower', 'refer' ] );
+__PACKAGE__->attributes( 'single', [ 'domain', 'refer', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'org', 'admin_c', 'tech_c', 'zone_c', 'nserver', 'ds_rdata', 'sub_dom', 'dom_net', 'remarks', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::Domain::AFRINIC - an object representation of a RPSL Domain block
+
+=head1 DESCRIPTION
+
+The domain object represents Top Level Domain (TLD) and other domain
+registrations.  It is also used for Reverse Delegations.  The domain
+name is written in fully qualified format, without a trailing " . "
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::Domain::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<domain( [$domain] )>
+
+Accessor to the domain attribute.
+Accepts an optional domain, always return the current domain.
+
+The domain name in fully qualified format, without a trailing dot. If a
+trailing dot is included it will be removed.
+
+=cut
+
+sub domain {
+    my ( $self, $domain ) = @_;
+
+    # Enforce the format
+    $domain =~ s/\.$// if $domain;
+
+    return $self->_single_attribute_setget( 'domain', $domain );
+}
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+The name of the organization responsible for the reverse delegation. Or can
+describe the use of the IP range described in the domain object.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation responsible for this domain.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<zone_c( [$contact] )>
+
+Accessor to the zone_c attribute.
+Accepts an optional contact to be added to the zone_c array,
+always return the current zone_c array.
+
+The NIC-handle of a 'person' or 'role' object with authority over a zone.
+
+=head2 B<nserver( [$server] )>
+
+Accessor to the nserver attribute.
+Accepts an optional server to be added to the nserver array,
+always return the current nserver array.
+
+A list of nameservers for a domain object. A minimum of one nameserver is
+mandatory.
+
+=head2 B<ds_rdata( [$server] )>
+
+Accessor to the ds_rdata attribute.
+Accepts an optional server to be added to the ds_rdata array,
+always return the current ds_rdata array.
+
+The ds_rdata attribute holds information about a signed delegation record
+for DNSSEC (short for DNS Security Extensions)
+
+=head2 B<sub_dom( [$dom] )>
+
+Accessor to the sub_dom attribute.
+Accepts an optional dom to be added to the sub_dom array,
+always return the current sub_dom array.
+
+The sub_dom attribute specifies a list of sub-domains of a domain. Domain
+names are relative to the domain represented by the domain object that
+contains this attribute
+
+=head2 B<dom_net( [$dom_net] )>
+
+Accessor to the dom_net attribute.
+Accepts an optional dom_net value to be added to the dom_net array,
+always return the current dom_net array.
+
+The dom_net attribute contains a list of IP networks in a domain.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or email address.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should be
+sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to
+this object.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+The identifier of a registered mntner object used to authorize the creation of
+reverse domain objects more specific than the reverse domain specified by this
+object.
+
+=head2 B<refer( [$refer] )>
+
+Accessor to the refer attribute.
+Accepts an optional refer, always return the current refer.
+
+The refer attribute is used to refer a query to another authorative
+database. See the "RIPE Database Query Reference Manual" for an
+explanation of its use. This will be redundant when forward domains are
+removed and may be deprecated.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -0,0 +1,238 @@
+package Net::Whois::Object::Domain::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t domain
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# domain:         [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# country:        [optional]   [single]     [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# zone-c:         [mandatory]  [multiple]   [inverse key]
+# nserver:        [optional]   [multiple]   [inverse key]
+# ds-rdata:       [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS4)
+
+    
+__PACKAGE__->attributes( 'primary',   ['domain'] );
+__PACKAGE__->attributes( 'mandatory', [ 'domain', 'descr', 'admin_c', 'tech_c', 'zone_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'country', 'org', 'nserver', 'ds_rdata', 'remarks', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single', [ 'domain', 'country', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'org', 'admin_c', 'tech_c', 'zone_c', 'nserver', 'ds_rdata', 'remarks', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::Domain::APNIC - an object representation of a RPSL Domain block
+
+=head1 DESCRIPTION
+
+The domain object represents Top Level Domain (TLD) and other domain
+registrations.  It is also used for Reverse Delegations.  The domain
+name is written in fully qualified format, without a trailing " . "
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::Domain::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<domain( [$domain] )>
+
+Accessor to the domain attribute.
+Accepts an optional domain, always return the current domain.
+
+The domain name in fully qualified format, without a trailing dot. If a
+trailing dot is included it will be removed.
+
+=cut
+
+sub domain {
+    my ( $self, $domain ) = @_;
+
+    # Enforce the format
+    $domain =~ s/\.$// if $domain;
+
+    return $self->_single_attribute_setget( 'domain', $domain );
+}
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+The name of the organization responsible for the reverse delegation. Or can
+describe the use of the IP range described in the domain object.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation responsible for this domain.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<zone_c( [$contact] )>
+
+Accessor to the zone_c attribute.
+Accepts an optional contact to be added to the zone_c array,
+always return the current zone_c array.
+
+The NIC-handle of a 'person' or 'role' object with authority over a zone.
+
+=head2 B<nserver( [$server] )>
+
+Accessor to the nserver attribute.
+Accepts an optional server to be added to the nserver array,
+always return the current nserver array.
+
+A list of nameservers for a domain object. A minimum of one nameserver is
+mandatory.
+
+=head2 B<ds_rdata( [$server] )>
+
+Accessor to the ds_rdata attribute.
+Accepts an optional server to be added to the ds_rdata array,
+always return the current ds_rdata array.
+
+The ds_rdata attribute holds information about a signed delegation record
+for DNSSEC (short for DNS Security Extensions)
+
+=head2 B<sub_dom( [$dom] )>
+
+Accessor to the sub_dom attribute.
+Accepts an optional dom to be added to the sub_dom array,
+always return the current sub_dom array.
+
+The sub_dom attribute specifies a list of sub-domains of a domain. Domain
+names are relative to the domain represented by the domain object that
+contains this attribute
+
+=head2 B<dom_net( [$dom_net] )>
+
+Accessor to the dom_net attribute.
+Accepts an optional dom_net value to be added to the dom_net array,
+always return the current dom_net array.
+
+The dom_net attribute contains a list of IP networks in a domain.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or email address.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should be
+sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to
+this object.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+The identifier of a registered mntner object used to authorize the creation of
+reverse domain objects more specific than the reverse domain specified by this
+object.
+
+=head2 B<refer( [$refer] )>
+
+Accessor to the refer attribute.
+Accepts an optional refer, always return the current refer.
+
+The refer attribute is used to refer a query to another authorative
+database. See the "RIPE Database Query Reference Manual" for an
+explanation of its use. This will be redundant when forward domains are
+removed and may be deprecated.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -0,0 +1,211 @@
+package Net::Whois::Object::FilterSet::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t filter-set -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# filter-set:     [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# filter:         [optional]   [single]     [ ]
+# mp-filter:      [optional]   [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary',   ['filter_set'] );
+__PACKAGE__->attributes( 'mandatory', [ 'filter_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'filter', 'mp_filter', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single',    [ 'filter_set', 'filter', 'mp_filter', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::FilterSet::AFRINIC - an object representation of a RPSL FilterSet block
+
+=head1 DESCRIPTION
+
+A FilterSet object defines a set of routes that match the criteria that you
+specify in your 'filter' – in other words it filters out routes that you do
+not want to see.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::FilterSet::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<filter_set( [$filter_set] )>
+
+Accessor to the filter_set attribute.
+Accepts an optional filter_set value, always return the current filter_set value.
+
+The filter_set attribute defines the name of the filter. It is an RPSL
+name that starts with "fltr-".
+
+The name of a filter_set object can be hierarchical:
+
+A hierarchical filter_set name is a sequence of filter_set names and AS
+Numbers separated by colons. At least one component of the name must be an
+actual filter_set name (i.e. start with "fltr-"). All the set name
+components of a hierarchical filter-name have to be filter_set names.
+
+=cut
+
+sub filter_set {
+    my ( $self, $filter_set ) = @_;
+    if ( $filter_set and $filter_set !~ /^fltr-/i ) {
+        warn "Incorrect FilterSet's name ($filter_set) : Should start with 'FLTR-'";
+    }
+
+    return $self->_single_attribute_setget( 'filter_set', $filter_set );
+}
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr value to be added to the descr array,
+always return the current descr array.
+
+A short description related to the object's purpose.
+
+=head2 B<filter( [$filter] )>
+
+Accessor to the filter attribute.
+Accepts an optional filter value, always return the current filter.
+
+The filter attribute defines the policy filter of the set.
+
+A policy filter is a logical expression which, when applied to a
+set of routes, returns a subset of these routes – the ones that
+you have said you want to see.
+
+=head2 B<mp_filter( [$mp_filter] )>
+
+Accessor to the mp_filter attribute.
+Accepts an optional mp_filter value, always return the current mp_filter.
+
+Logical expression which when applied to a set of IPv4 or IPv6 routes returns
+a subset of these routes.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or email address.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation responsible for this FilterSet object.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to this
+object.
+
+When the database details are protected by a Mntner object, then
+only persons with access to the security information of that Mntner
+object will be able to change details.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+Sometimes there is a hierarchy of maintainers. In these cases, mnt_lower is
+used as well as mnt_by.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -0,0 +1,214 @@
+package Net::Whois::Object::FilterSet::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t filter-set
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# filter-set:     [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# filter:         [optional]   [single]     [ ]
+# mp-filter:      [optional]   [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS2)
+
+__PACKAGE__->attributes( 'primary',   [ 'filter_set' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'filter_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'filter', 'mp_filter', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single',    [ 'filter_set', 'filter', 'mp_filter', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::FilterSet::APNIC - an object representation of a RPSL FilterSet block
+
+=head1 DESCRIPTION
+
+A FilterSet object defines a set of routes that match the criteria that you
+specify in your 'filter' – in other words it filters out routes that you do
+not want to see.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::FilterSet::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<filter_set( [$filter_set] )>
+
+Accessor to the filter_set attribute.
+Accepts an optional filter_set value, always return the current filter_set value.
+
+The filter_set attribute defines the name of the filter. It is an RPSL
+name that starts with "fltr-".
+
+The name of a filter_set object can be hierarchical:
+
+A hierarchical filter_set name is a sequence of filter_set names and AS
+Numbers separated by colons. At least one component of the name must be an
+actual filter_set name (i.e. start with "fltr-"). All the set name
+components of a hierarchical filter-name have to be filter_set names.
+
+=cut
+
+sub filter_set {
+    my ( $self, $filter_set ) = @_;
+    if ( $filter_set and $filter_set !~ /^fltr-/i ) {
+        warn "Incorrect FilterSet's name ($filter_set) : Should start with 'FLTR-'";
+    }
+
+    return $self->_single_attribute_setget( 'filter_set', $filter_set );
+}
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr value to be added to the descr array,
+always return the current descr array.
+
+A short description related to the object's purpose.
+
+=head2 B<filter( [$filter] )>
+
+Accessor to the filter attribute.
+Accepts an optional filter value, always return the current filter.
+
+The filter attribute defines the policy filter of the set.
+
+A policy filter is a logical expression which, when applied to a
+set of routes, returns a subset of these routes – the ones that
+you have said you want to see.
+
+=head2 B<mp_filter( [$mp_filter] )>
+
+Accessor to the mp_filter attribute.
+Accepts an optional mp_filter value, always return the current mp_filter.
+
+Logical expression which when applied to a set of IPv4 or IPv6 routes returns
+a subset of these routes.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or email address.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation responsible for this FilterSet object.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to this
+object.
+
+When the database details are protected by a Mntner object, then
+only persons with access to the security information of that Mntner
+object will be able to change details.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+Sometimes there is a hierarchy of maintainers. In these cases, mnt_lower is
+used as well as mnt_by.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -0,0 +1,263 @@
+package Net::Whois::Object::Inet6Num::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t inet6num -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# inet6num:       [mandatory]  [single]     [primary/look-up key]
+# netname:        [mandatory]  [single]     [lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# country:        [mandatory]  [multiple]   [ ]
+# org:            [optional]   [single]     [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# status:         [mandatory]  [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-domains:    [optional]   [multiple]   [inverse key]
+# mnt-irt:        [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# parent:         [generated]  [multiple]   [ ]
+
+__PACKAGE__->attributes( 'primary',   ['inet6num'] );
+__PACKAGE__->attributes( 'mandatory', [ 'inet6num', 'netname', 'descr', 'country', 'admin_c', 'tech_c', 'status', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', ['org', 'remarks', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_domains', 'mnt_irt' ] );
+__PACKAGE__->attributes( 'single', [ 'inet6num', 'netname', 'org', 'status', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'country', 'admin_c', 'tech_c', 'remarks', 'notify', 'mnt_by', 'mnt_lower', 'mnt_routes', 'mnt_domains', 'mnt_irt', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Inet6Num::AFRINIC - an object representation of a RPSL Inet6Num block
+
+=head1 DESCRIPTION
+
+An inet6num object contains information on allocations and assignments
+of IPv6 address space.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::Inet6Num::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<inet6num( [$inet6num] )>
+
+Accessor to the inet6num attribute.
+Accepts an optional inet6num value, always return the current inet6num value.
+
+The inet6num attribute specifies a range of IPv6 addresses that the
+inet6num object presents. The range may be a single address.
+
+Addresses can only be expressed in prefix notation
+
+=head2 B<netname( [$netname] )>
+
+Accessor to the netname attribute.
+Accepts an optional netname, always return the current netname.
+
+The netname attribute is the name of a range of IP address space. It is
+recommended that the same netname is used for any set of assignment ranges
+used for a common purpose.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr to be added to the descr array,
+always return the current descr array.
+
+Description of the organization allocated or assigned the address space shown
+in the inet6num.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country to be added to the country array,
+always return the current country array.
+
+The country attribute identifies the country. It has never been specified
+if this is the country where the addresses are used, where the issuing
+organisation is based or some transit country in between. There are no rules
+defined for this attribute. It cannot therefore be used in any reliable way to
+map IP addresses to countries.
+
+=head2 B<geoloc( [$geoloc] )>
+
+Accessor to the geoloc attribute.
+Accepts an optional geoloc, always return the current geoloc.
+
+The location coordinates for the resource
+
+Location coordinates of the resource. Can take one of the following forms:
+[-90,90][-180,180]
+
+=head2 B<language( [$language] )>
+
+Accessor to the language attribute.
+Accepts an optional language to be added to the language array,
+always return the current language array.
+
+Identifies the language.
+
+Valid two-letter ISO 639-1 language code.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Only a single value for the org attribute is allowed in the inet6num
+object. This is to ensure only one organisation is responsible for this
+resource.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+
+=head2 B<status( [$status] )>
+
+Accessor to the status attribute.
+Accepts an optional status, always return the current status.
+
+The status attribute indicates where the address range represented by an
+inet6num object sits in a hierarchy and how it is used.
+
+Status can have one of these values:
+
+=over 4
+
+=item ALLOCATED-BY-RIR
+
+=item ALLOCATED-BY-LIR
+
+=item ASSIGNED
+
+=item ASSIGNED ANYCAST
+
+=item ASSIGNED PI
+
+=back
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or instructions on where to send abuse
+complaints.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should be
+sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+Sometimes there is a hierarchy of maintainers. In these cases, mnt-lower is
+used as well as 'mnt-by.'
+
+=head2 B<mnt_routes( [$mnt_route] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_route to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+The identifier of a registered Mntner object used to control the creation of
+Route6 objects associated with the address range specified by the Inet6num
+object.
+
+=head2 B<mnt_domains( [$mnt_route] )>
+
+Accessor to the mnt_domains attribute.
+Accepts an optional mnt_route to be added to the mnt_domains array,
+always return the current mnt_domains array.
+
+The identifier of a registered Mntner object used to control the creation of
+Domain objects associated with the address range specified by the Inet6num
+object.
+
+=head2 B<mnt_irt( [$mnt_irt] )>
+
+Accessor to the mnt_irt attribute.
+Accepts an optional mnt_irt to be added to the mnt_irt array,
+always return the current mnt_irt array.
+
+mnt_irt references an Irt object. Authorisation is required from the Irt
+object to be able to add this reference.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -0,0 +1,265 @@
+package Net::Whois::Object::Inet6Num::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t inet6num
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# inet6num:       [mandatory]  [single]     [primary/lookup key]
+# netname:        [mandatory]  [single]     [lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# country:        [mandatory]  [multiple]   [ ]
+# geoloc:         [optional]   [single]     [ ]
+# language:       [optional]   [multiple]   [ ]
+# org:            [optional]   [single]     [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# status:         [mandatory]  [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-irt:        [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+
+__PACKAGE__->attributes( 'primary',   [ 'inet6num'] );
+__PACKAGE__->attributes( 'mandatory', [ 'inet6num', 'netname', 'descr', 'country', 'admin_c', 'tech_c', 'status', 'mnt_by', 'mnt_irt', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'geoloc', 'language', 'org', 'remarks', 'notify', 'mnt_lower', 'mnt_routes' ] );
+__PACKAGE__->attributes( 'single',    [ 'inet6num', 'netname', 'geoloc', 'org', 'status', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'country', 'language', 'admin_c', 'tech_c', 'remarks', 'notify', 'mnt_by', 'mnt_lower', 'mnt_routes', 'mnt_irt', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Inet6Num::APNIC - an object representation of a RPSL Inet6Num block
+
+=head1 DESCRIPTION
+
+An inet6num object contains information on allocations and assignments
+of IPv6 address space.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::Inet6Num::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<inet6num( [$inet6num] )>
+
+Accessor to the inet6num attribute.
+Accepts an optional inet6num value, always return the current inet6num value.
+
+The inet6num attribute specifies a range of IPv6 addresses that the
+inet6num object presents. The range may be a single address.
+
+Addresses can only be expressed in prefix notation
+
+=head2 B<netname( [$netname] )>
+
+Accessor to the netname attribute.
+Accepts an optional netname, always return the current netname.
+
+The netname attribute is the name of a range of IP address space. It is
+recommended that the same netname is used for any set of assignment ranges
+used for a common purpose.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr to be added to the descr array,
+always return the current descr array.
+
+Description of the organization allocated or assigned the address space shown
+in the inet6num.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country to be added to the country array,
+always return the current country array.
+
+The country attribute identifies the country. It has never been specified
+if this is the country where the addresses are used, where the issuing
+organisation is based or some transit country in between. There are no rules
+defined for this attribute. It cannot therefore be used in any reliable way to
+map IP addresses to countries.
+
+=head2 B<geoloc( [$geoloc] )>
+
+Accessor to the geoloc attribute.
+Accepts an optional geoloc, always return the current geoloc.
+
+The location coordinates for the resource
+
+Location coordinates of the resource. Can take one of the following forms:
+[-90,90][-180,180]
+
+=head2 B<language( [$language] )>
+
+Accessor to the language attribute.
+Accepts an optional language to be added to the language array,
+always return the current language array.
+
+Identifies the language.
+
+Valid two-letter ISO 639-1 language code.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Only a single value for the org attribute is allowed in the inet6num
+object. This is to ensure only one organisation is responsible for this
+resource.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact 'person' object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact 'person' or 'role' object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+
+=head2 B<status( [$status] )>
+
+Accessor to the status attribute.
+Accepts an optional status, always return the current status.
+
+The status attribute indicates where the address range represented by an
+inet6num object sits in a hierarchy and how it is used.
+
+Status can have one of these values:
+
+=over 4
+
+=item ALLOCATED-BY-RIR
+
+=item ALLOCATED-BY-LIR
+
+=item ASSIGNED
+
+=item ASSIGNED ANYCAST
+
+=item ASSIGNED PI
+
+=back
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or instructions on where to send abuse
+complaints.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should be
+sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+Sometimes there is a hierarchy of maintainers. In these cases, mnt-lower is
+used as well as 'mnt-by.'
+
+=head2 B<mnt_routes( [$mnt_route] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_route to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+The identifier of a registered Mntner object used to control the creation of
+Route6 objects associated with the address range specified by the Inet6num
+object.
+
+=head2 B<mnt_domains( [$mnt_route] )>
+
+Accessor to the mnt_domains attribute.
+Accepts an optional mnt_route to be added to the mnt_domains array,
+always return the current mnt_domains array.
+
+The identifier of a registered Mntner object used to control the creation of
+Domain objects associated with the address range specified by the Inet6num
+object.
+
+=head2 B<mnt_irt( [$mnt_irt] )>
+
+Accessor to the mnt_irt attribute.
+Accepts an optional mnt_irt to be added to the mnt_irt array,
+always return the current mnt_irt array.
+
+mnt_irt references an Irt object. Authorisation is required from the Irt
+object to be able to add this reference.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -5,7 +5,7 @@ use base qw/Net::Whois::Object/;
 # http://www.ripe.net/data-tools/support/documentation/update-ref-manual#section-12
 # http://www.apnic.net/apnic-info/whois_search/using-whois/guide/inet6num
 #
-# From : whois -t inet6num  
+# From: whois -t inet6num  
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
@@ -39,8 +39,8 @@ use base qw/Net::Whois::Object/;
 # mnt-irt:       [mandatory]  [single]     [inverse key]
 __PACKAGE__->attributes( 'primary',   ['inet6num'] );
 __PACKAGE__->attributes( 'mandatory', [ 'inet6num', 'netname', 'status', 'source' ] );
-__PACKAGE__->attributes( 'optional', ['geoloc', 'language', 'org', 'remarks', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_domains', 'mnt_irt' ] );
-__PACKAGE__->attributes( 'single', [ 'inet6num', 'netname', 'geoloc', 'org', 'status', 'source' ] );
+__PACKAGE__->attributes( 'optional', ['geoloc', 'language', 'org', 'remarks', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_domains', 'mnt_irt', 'assignment_size' ] );
+__PACKAGE__->attributes( 'single', [ 'inet6num', 'netname', 'geoloc', 'org', 'status', 'source', 'assignment_size' ] );
 __PACKAGE__->attributes( 'multiple', [ 'descr', 'country','language', 'tech_c', 'admin_c', 'remarks', 'notify', 'mnt_by', 'mnt_lower', 'mnt_routes', 'mnt_domains', 'mnt_irt', 'changed' ] );
 
 =head1 NAME
@@ -0,0 +1,264 @@
+package Net::Whois::Object::InetNum::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+#
+# whois -h whois.afrinic.net -t inetnum
+# 
+# % This is the AfriNIC Whois server.
+# 
+# inetnum:        [mandatory]  [single]     [primary/look-up key]
+# netname:        [mandatory]  [single]     [lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# country:        [mandatory]  [multiple]   [ ]
+# org:            [optional]   [single]     [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# status:         [mandatory]  [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-domains:    [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-irt:        [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# parent:         [generated]  [multiple]   [ ]
+
+
+__PACKAGE__->attributes( 'primary', ['inetnum'] );
+__PACKAGE__->attributes( 'mandatory', [ 'inetnum', 'netname', 'descr', 'country', 'admin_c', 'tech_c', 'status', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'org', 'remarks', 'notify', 'mnt_lower', 'mnt_domains', 'mnt_routes', 'mnt_irt', 'parent' ] );
+__PACKAGE__->attributes( 'single', [ 'inetnum', 'netname', 'geoloc', 'org', 'status', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'country', 'admin_c', 'tech_c', 'remarks', 'notify', 'mnt_by', 'mnt_lower', 'mnt_domains', 'mnt_routes', 'mnt_irt', 'changed', 'parent' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::InetNum::AFRINIC - an object representation of a RPSL InetNum block
+
+=head1 DESCRIPTION
+
+An inetnum object contains information on allocations and assignments
+of IPv4 address space.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::InetNum::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<inetnum( [$inetnum] )>
+
+Accessor to the inetnum attribute.
+Accepts an optional inetnum value, always return the current inetnum value.
+
+=head2 B<netname( [$netname] )>
+
+Accessor to the netname attribute.
+Accepts an optional netname, always return the current netname.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr value to be added to the descr array,
+always return the current descr array.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country to be added to the country array,
+always return the current country array.
+
+=head2 B<geoloc( [$geoloc] )>
+
+Accessor to the geoloc attribute.
+Accepts an optional geoloc, always return the current geoloc.
+
+The location coordinates for the resource
+
+Location coordinates of the resource. Can take one of the following forms:
+[-90,90][-180,180]
+
+=head2 B<language( [$language] )>
+
+Accessor to the language attribute.
+Accepts an optional language to be added to the language array,
+always return the current language array.
+
+Identifies the language.
+
+Valid two-letter ISO 639-1 language code.
+=head2 B<org( [$org] )>
+
+Accessor to the 'org' attribute.
+Accepts an optional org, always return the current org.
+
+Only a single value for the org attribute is allowed in the Inetnum object.
+This is to ensure only one organisation is responsible for this resource.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact Person object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact Person or Role object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<status( [$status] )>
+
+Accessor to the 'status' attribute.
+Accepts an optional status, always return the current status.
+
+The status attribute indicates where the address range represented by an
+inetnum object sits in a hierarchy and how it is used.
+
+Status can have one of these values:
+
+=over 4
+
+=item ALLOCATED UNSPECIFIED
+
+=item ALLOCATED PA
+
+=item ALLOCATED PI
+
+=item LIR-PARTITIONED PA
+
+=item LIR-PARTITIONED PI
+
+=item SUB-ALLOCATED PA
+
+=item ASSIGNED PA
+
+=item ASSIGNED PI
+
+=item ASSIGNED ANYCAST
+
+=item EARLY-REGISTRATION
+
+=item NOT-SET
+
+=back
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or instructions on where to send abuse
+complaints.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should be
+sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered Mntner used to authorize and authenticate changes to this
+object.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+Sometimes there is a hierarchy of maintainers. In these cases, mnt_lower is
+used as well as mnt_by.
+
+=head2 B<mnt_routes( [$mnt_route] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_route to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+The identifier of a registered Mntner object used to control the creation of
+Route objects associated with the address range specified by the Inetnum
+object.
+
+=head2 B<mnt_domains( [$mnt_domain] )>
+
+Accessor to the mnt_domains attribute.
+Accepts an optional mnt_domain to be added to the mnt_domains array,
+always return the current mnt_domains array.
+
+The identifier of a registered Mntner object used to control the creation of
+Domain objects associated with the address range specified by the Inetnum
+object.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<mnt_irt( [$mnt_irt] )>
+
+Accessor to the mnt_irt attribute.
+Accepts an optional mnt_irt value to be added to the mnt_irt array,
+always return the current mnt_irt array.
+
+The identifier of a registered Mntner object used to provide information
+about a Computer Security Incident Response Team (CSIRT).
+
+=cut
+
+1;
@@ -0,0 +1,263 @@
+package Net::Whois::Object::InetNum::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t inetnum
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# inetnum:        [mandatory]  [single]     [primary/lookup key]
+# netname:        [mandatory]  [single]     [lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# country:        [mandatory]  [multiple]   [ ]
+# geoloc:         [optional]   [single]     [ ]
+# language:       [optional]   [multiple]   [ ]
+# org:            [optional]   [single]     [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# status:         [mandatory]  [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-irt:        [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS4)
+
+__PACKAGE__->attributes( 'primary',   [ 'inetnum' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'inetnum', 'netname', 'descr', 'country', 'admin_c', 'tech_c', 'status', 'mnt_by', 'mnt_irt', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'geoloc', 'language', 'org', 'remarks', 'notify', 'mnt_lower', 'mnt_routes' ] );
+__PACKAGE__->attributes( 'single',    [ 'inetnum', 'netname', 'geoloc', 'org', 'status', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'country', 'language', 'admin_c', 'tech_c', 'remarks', 'notify', 'mnt_by', 'mnt_lower', 'mnt_routes', 'mnt_irt', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::InetNum::APNIC - an object representation of a RPSL InetNum block
+
+=head1 DESCRIPTION
+
+An inetnum object contains information on allocations and assignments
+of IPv4 address space.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::InetNum::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<inetnum( [$inetnum] )>
+
+Accessor to the inetnum attribute.
+Accepts an optional inetnum value, always return the current inetnum value.
+
+=head2 B<netname( [$netname] )>
+
+Accessor to the netname attribute.
+Accepts an optional netname, always return the current netname.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr value to be added to the descr array,
+always return the current descr array.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country to be added to the country array,
+always return the current country array.
+
+=head2 B<geoloc( [$geoloc] )>
+
+Accessor to the geoloc attribute.
+Accepts an optional geoloc, always return the current geoloc.
+
+The location coordinates for the resource
+
+Location coordinates of the resource. Can take one of the following forms:
+[-90,90][-180,180]
+
+=head2 B<language( [$language] )>
+
+Accessor to the language attribute.
+Accepts an optional language to be added to the language array,
+always return the current language array.
+
+Identifies the language.
+
+Valid two-letter ISO 639-1 language code.
+=head2 B<org( [$org] )>
+
+Accessor to the 'org' attribute.
+Accepts an optional org, always return the current org.
+
+Only a single value for the org attribute is allowed in the Inetnum object.
+This is to ensure only one organisation is responsible for this resource.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact Person object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact Person or Role object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<status( [$status] )>
+
+Accessor to the 'status' attribute.
+Accepts an optional status, always return the current status.
+
+The status attribute indicates where the address range represented by an
+inetnum object sits in a hierarchy and how it is used.
+
+Status can have one of these values:
+
+=over 4
+
+=item ALLOCATED UNSPECIFIED
+
+=item ALLOCATED PA
+
+=item ALLOCATED PI
+
+=item LIR-PARTITIONED PA
+
+=item LIR-PARTITIONED PI
+
+=item SUB-ALLOCATED PA
+
+=item ASSIGNED PA
+
+=item ASSIGNED PI
+
+=item ASSIGNED ANYCAST
+
+=item EARLY-REGISTRATION
+
+=item NOT-SET
+
+=back
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or instructions on where to send abuse
+complaints.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should be
+sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered Mntner used to authorize and authenticate changes to this
+object.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+Sometimes there is a hierarchy of maintainers. In these cases, mnt_lower is
+used as well as mnt_by.
+
+=head2 B<mnt_routes( [$mnt_route] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_route to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+The identifier of a registered Mntner object used to control the creation of
+Route objects associated with the address range specified by the Inetnum
+object.
+
+=head2 B<mnt_domains( [$mnt_domain] )>
+
+Accessor to the mnt_domains attribute.
+Accepts an optional mnt_domain to be added to the mnt_domains array,
+always return the current mnt_domains array.
+
+The identifier of a registered Mntner object used to control the creation of
+Domain objects associated with the address range specified by the Inetnum
+object.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<mnt_irt( [$mnt_irt] )>
+
+Accessor to the mnt_irt attribute.
+Accepts an optional mnt_irt value to be added to the mnt_irt array,
+always return the current mnt_irt array.
+
+The identifier of a registered Mntner object used to provide information
+about a Computer Security Incident Response Team (CSIRT).
+
+=cut
+
+1;
@@ -5,7 +5,7 @@ use base qw/Net::Whois::Object/;
 # http://www.ripe.net/data-tools/support/documentation/update-ref-manual#section-13
 # http://www.apnic.net/apnic-info/whois_search/using-whois/guide/inetnum
 #
-# From :  whois -t inetnum 
+# From:  whois -t inetnum 
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
@@ -0,0 +1,226 @@
+package Net::Whois::Object::InetRtr::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t inet-rtr -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# inet-rtr:       [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# alias:          [optional]   [multiple]   [ ]
+# local-as:       [mandatory]  [single]     [inverse key]
+# ifaddr:         [mandatory]  [multiple]   [lookup key]
+# interface:      [optional]   [multiple]   [lookup key]
+# peer:           [optional]   [multiple]   [ ]
+# mp-peer:        [optional]   [multiple]   [ ]
+# member-of:      [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['inet_rtr'] );
+__PACKAGE__->attributes( 'mandatory', [ 'inet_rtr', 'descr', 'local_as', 'ifaddr', 'admin_c', 'tech_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'alias', 'interface', 'peer', 'mp_peer', 'member_of', 'remarks', 'org', 'notify' ] );
+__PACKAGE__->attributes( 'single', [ 'inet_rtr', 'local_as', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'alias', 'ifaddr', 'interface', 'peer', 'mp_peer', 'member_of', 'remarks', 'org', 'admin_c', 'tech_c', 'notify', 'mnt_by', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::InetRtr::AFRINIC - an object representation of a RPSL InetRtr block
+
+=head1 DESCRIPTION
+
+The inet-rtr object specifies routers.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::InetRtr::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<inet_rtr( [$inet_rtr] )>
+
+Accessor to the inet_rtr attribute.
+Accepts an optional inet_rtr, always return the current inet_rtr value.
+
+The inet_rtr attribute is a valid DNS name for a router without a trailing
+dot.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr value to be added to the descr array,
+always return the current descr array.
+
+A short description related to the object's purpose.
+
+=head2 B<alias( [$alias] )>
+
+Accessor to the alias attribute.
+Accepts an optional alias to be added to the alias array,
+always return the current alias array.
+
+Each alias attribute, if present, is also standard DNS name for the
+specified router.
+
+=head2 B<local_as( [$local_as] )>
+
+Accessor to the local_as attribute.
+Accepts an optional local_as, always return the current local_as.
+
+The local_as attribute specifies the AS Number of the AS that owns or
+operates this router.
+
+=head2 B<ifaddr( [$ifaddr] )>
+
+Accessor to the ifaddr attribute.
+Accepts an optional ifaddr value to be added to the ifaddr array,
+always return the current ifaddr array.
+
+The ifaddr attribute specifies the interface address within an Internet
+router, as well as an optional action to set other parameters on this
+interface.
+
+=head2 B<peer( [$peer] )>
+
+Accessor to the peer attribute.
+Accepts an optional peer to be added to the peer array,
+always return the current peer array.
+
+The peer attribute specifies the details of any interior or exterior router
+peering.
+
+=head2 B<member_of( [$member_of] )>
+
+Accessor to the member_of attribute.
+Accepts an optional member_of value to be be added to the member_of array,
+always return the current member_of array.
+
+The member_of attribute value identifies a set object that this object
+wants to be a member of. This claim, however, should be acknowledged by a
+respective mbrs-by-ref attribute in the referenced object.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or instructions on where to send abuse
+complaints.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact Person object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact Person or Role object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should
+be sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered 'mntner' used to authorize and authenticate changes to this
+object.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<mp_peer( [$peer] )>
+
+Accessor to the mp_peer attribute.
+Accepts an optional peer to be added to the mp_peer array,
+always return the current mp_peer array.
+
+This attribute performs the same function as the peer attribute above. The
+difference is that mp-peer allows both IPv4 and IPv6 address families to be
+specified.
+
+The mp-peer attribute extends the peer attribute for IPv6 addresses.
+
+=head2 B<interface( [$interface] )>
+
+Accessor to the interface attribute.
+Accepts an optional interface to be added to the interface array,
+always return the current interface array.
+
+The interface attribute specifies a multi-protocol interface address within
+an Internet router, optional action and tunnel definition.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org to be added to the org array,
+always return the current org array.
+
+The organisation entity this object is bound to.
+
+=cut
+
+1;
@@ -0,0 +1,51 @@
+package Net::Whois::Object::Information;
+
+use base qw/Net::Whois::Object/;
+
+__PACKAGE__->attributes( 'mandatory', ['comment'] );
+__PACKAGE__->attributes( 'optional', [] );
+__PACKAGE__->attributes( 'multiple',  ['comment'] );
+
+=head1 NAME
+
+Net::Whois::Object::Information - an object representation of the RPSL Information block
+
+=head1 DESCRIPTION
+
+output starting with the % sign is either a server response code or
+an informational message. A comment contains a white space after the
+% sign, while server messages start right after the % sign. Please
+see Appendix A2 "RIPE Database response codes and messages" for more
+information.
+
+* An empty line ("\n\n") is an object delimiter. 
+
+* Two empty lines mean the end of a server response. The "members:" attribute lists the members of the set.  The
+"members:" attribute is a list of AS numbers, or other as-set names.
+
+=head1 METHODS
+
+=head2 new ( @options )
+
+Constructor for the Net::Whois::Object::Information class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<comment( [$comment] )>
+
+Accessor to the comment attribute.
+Accepts an optional comment to be added to the comment array,
+always return the current comment array.
+
+=cut
+
+1;
@@ -0,0 +1,261 @@
+package Net::Whois::Object::Irt::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t irt -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# irt:            [mandatory]  [single]     [primary/look-up key]
+# address:        [mandatory]  [multiple]   [ ]
+# phone:          [optional]   [multiple]   [ ]
+# fax-no:         [optional]   [multiple]   [ ]
+# e-mail:         [mandatory]  [multiple]   [lookup key]
+# abuse-mailbox:  [mandatory]  [multiple]   [inverse key]
+# signature:      [optional]   [multiple]   [ ]
+# encryption:     [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# auth:           [mandatory]  [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# irt-nfy:        [optional]   [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['irt'] );
+__PACKAGE__->attributes( 'mandatory', [ 'irt', 'address', 'e_mail', 'abuse_mailbox', 'admin_c', 'tech_c', 'auth', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'phone', 'fax_no', 'signature', 'encryption', 'org', 'remarks', 'irt_nfy', 'notify' ] );
+__PACKAGE__->attributes( 'single', [ 'irt', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'address', 'phone', 'fax_no', 'e_mail', 'abuse_mailbox', 'signature', 'encryption', 'org', 'admin_c', 'tech_c', 'auth', 'remarks', 'irt_nfy', 'notify', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Irt::AFRINIC - an object representation of the RPSL Irt block
+
+=head1 DESCRIPTION
+
+The irt object is used to provide information about a Computer Security
+Incident Response Team (CSIRT).  IRTs or CSIRTs specifically respond to
+computer security incident reports and activity.
+
+They are dedicated abuse handling teams, (as distinct from network operational
+departments) which review and respond to abuse reports.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Irt::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+
+}
+
+=head2 B<irt( [$irt] )>
+
+Accessor to the irt attribute.
+Accepts an optional irt, always return the current irt.
+
+The irt object name starts with "IRT-".
+
+=cut
+
+sub irt {
+    my ( $self, $irt ) = @_;
+    if ( $irt and $irt !~ /^IRT-/i ) {
+        warn "Irt name not valid ($irt) : Should start with 'IRT-'";
+    }
+    return $self->_single_attribute_setget( 'irt', $irt );
+}
+
+=head2 B<address( [$address] )>
+
+Accessor to the address attribute.
+Accepts an optional address to be added to the address array,
+always return the current address array.
+
+Full postal address of a contact.
+
+You can use any combination of alphanumeric characters.
+More than one line can be used.
+
+=cut
+
+sub address {
+    my ( $self, $address ) = @_;
+
+    return $self->_multiple_attribute_setget( 'address', $address );
+}
+
+=head2 B<phone( [$phone] )>
+
+Accessor to the phone attribute.
+Accepts an optional phone number to be added to the phone array,
+always return the current phone array.
+
+A contact telephone number.
+
++ <international code> <area code> <phone #>
+
++ <international code> <area code> <phone #> ext. <#>
+
+ EXAMPLE
+ phone: +681 368 0844 ext. 32
+
+=head2 B<fax_no( [$fax_no] )>
+
+Accessor to the fax_no attribute.
+Accepts an optional fax_no to be added to the fax_no array,
+always return the current fax_no array.
+
+A contact fax number.
+
++ <international code> <area code> <fax #>
+
+=head2 B<e_mail( [$e_mail] )>
+
+Accessor to the e_mail attribute.
+Accepts an optional e_mail to be added to the e_mail array,
+always return the current e_mail array.
+
+A contact email address for non-abuse/technical incidents.
+
+=head2 B<abuse_mailbox( [$abuse_mailbox] )>
+
+Accessor to the abuse_mailbox attribute.
+Accepts an optional abuse_mailbox to be added to the abuse_mailbox array,
+always return the current abuse_mailbox array.
+
+Specifies the email address to which abuse complaints should be sent.
+
+=head2 B<signature( [$signature] )>
+
+Accessor to the signature attribute.
+Accepts an optional signature to be added to the signature array,
+always return the current signature array.
+
+References a KeyCert object representing a CSIRT public key used by the
+team to sign their correspondence.
+
+=head2 B<encryption( [$encryption] )>
+
+Accessor to the encryption attribute.
+Accepts an optional encryption to be added to the encryption array,
+always return the current encryption array.
+
+References a KeyCert object representing a CSIRT public key used to encrypt
+correspondence sent to the CSIRT.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation responsible for this resource.
+
+=head2 B<auth( [$auth] )>
+
+Accessor to the auth attribute.
+Accepts an optional auth to be added to the auth array,
+always return the current auth array.
+
+The Auth defines an authentication scheme to be used. Any of the current
+authentication schemes used by the RIPE Database are allowed.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site administrative contact. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact. As more than one person often fulfills
+a role function, there may be more than one tech_c listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+Information about the object that cannot be stated in other attributes.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should
+be sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered Mntner used to authorize and authenticate changes to
+this object.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<irt_nfy( [$irt_nfy] )>
+
+Accessor to the irt_nfy attribute.
+Accepts an optional irt_nfy value to be added to the irt_nfy array,
+always return the current irt_nfy array.
+
+The irt_nfy attribute specifies the email address to be notified when a
+reference to the irt object is added or removed.
+
+=cut
+
+1;
@@ -0,0 +1,261 @@
+package Net::Whois::Object::Irt::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t irt -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# irt:            [mandatory]  [single]     [primary/look-up key]
+# address:        [mandatory]  [multiple]   [ ]
+# phone:          [optional]   [multiple]   [ ]
+# fax-no:         [optional]   [multiple]   [ ]
+# e-mail:         [mandatory]  [multiple]   [lookup key]
+# abuse-mailbox:  [mandatory]  [multiple]   [inverse key]
+# signature:      [optional]   [multiple]   [ ]
+# encryption:     [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# auth:           [mandatory]  [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# irt-nfy:        [optional]   [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary',   [ 'irt' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'irt', 'address', 'e_mail', 'abuse_mailbox', 'admin_c', 'tech_c', 'auth', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'phone', 'fax_no', 'signature', 'encryption', 'org', 'remarks', 'irt_nfy', 'notify' ] );
+__PACKAGE__->attributes( 'single',    [ 'irt', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'address', 'phone', 'fax_no', 'e_mail', 'abuse_mailbox', 'signature', 'encryption', 'org', 'admin_c', 'tech_c', 'auth', 'remarks', 'irt_nfy', 'notify', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Irt::APNIC - an object representation of the RPSL Irt block
+
+=head1 DESCRIPTION
+
+The irt object is used to provide information about a Computer Security
+Incident Response Team (CSIRT).  IRTs or CSIRTs specifically respond to
+computer security incident reports and activity.
+
+They are dedicated abuse handling teams, (as distinct from network operational
+departments) which review and respond to abuse reports.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Irt::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+
+}
+
+=head2 B<irt( [$irt] )>
+
+Accessor to the irt attribute.
+Accepts an optional irt, always return the current irt.
+
+The irt object name starts with "IRT-".
+
+=cut
+
+sub irt {
+    my ( $self, $irt ) = @_;
+    if ( $irt and $irt !~ /^IRT-/i ) {
+        warn "Irt name not valid ($irt) : Should start with 'IRT-'";
+    }
+    return $self->_single_attribute_setget( 'irt', $irt );
+}
+
+=head2 B<address( [$address] )>
+
+Accessor to the address attribute.
+Accepts an optional address to be added to the address array,
+always return the current address array.
+
+Full postal address of a contact.
+
+You can use any combination of alphanumeric characters.
+More than one line can be used.
+
+=cut
+
+sub address {
+    my ( $self, $address ) = @_;
+
+    return $self->_multiple_attribute_setget( 'address', $address );
+}
+
+=head2 B<phone( [$phone] )>
+
+Accessor to the phone attribute.
+Accepts an optional phone number to be added to the phone array,
+always return the current phone array.
+
+A contact telephone number.
+
++ <international code> <area code> <phone #>
+
++ <international code> <area code> <phone #> ext. <#>
+
+ EXAMPLE
+ phone: +681 368 0844 ext. 32
+
+=head2 B<fax_no( [$fax_no] )>
+
+Accessor to the fax_no attribute.
+Accepts an optional fax_no to be added to the fax_no array,
+always return the current fax_no array.
+
+A contact fax number.
+
++ <international code> <area code> <fax #>
+
+=head2 B<e_mail( [$e_mail] )>
+
+Accessor to the e_mail attribute.
+Accepts an optional e_mail to be added to the e_mail array,
+always return the current e_mail array.
+
+A contact email address for non-abuse/technical incidents.
+
+=head2 B<abuse_mailbox( [$abuse_mailbox] )>
+
+Accessor to the abuse_mailbox attribute.
+Accepts an optional abuse_mailbox to be added to the abuse_mailbox array,
+always return the current abuse_mailbox array.
+
+Specifies the email address to which abuse complaints should be sent.
+
+=head2 B<signature( [$signature] )>
+
+Accessor to the signature attribute.
+Accepts an optional signature to be added to the signature array,
+always return the current signature array.
+
+References a KeyCert object representing a CSIRT public key used by the
+team to sign their correspondence.
+
+=head2 B<encryption( [$encryption] )>
+
+Accessor to the encryption attribute.
+Accepts an optional encryption to be added to the encryption array,
+always return the current encryption array.
+
+References a KeyCert object representing a CSIRT public key used to encrypt
+correspondence sent to the CSIRT.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation responsible for this resource.
+
+=head2 B<auth( [$auth] )>
+
+Accessor to the auth attribute.
+Accepts an optional auth to be added to the auth array,
+always return the current auth array.
+
+The Auth defines an authentication scheme to be used. Any of the current
+authentication schemes used by the RIPE Database are allowed.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site administrative contact. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact. As more than one person often fulfills
+a role function, there may be more than one tech_c listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+Information about the object that cannot be stated in other attributes.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should
+be sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered Mntner used to authorize and authenticate changes to
+this object.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=head2 B<irt_nfy( [$irt_nfy] )>
+
+Accessor to the irt_nfy attribute.
+Accepts an optional irt_nfy value to be added to the irt_nfy array,
+always return the current irt_nfy array.
+
+The irt_nfy attribute specifies the email address to be notified when a
+reference to the irt object is added or removed.
+
+=cut
+
+1;
@@ -0,0 +1,205 @@
+package Net::Whois::Object::KeyCert::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t key-cert -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# key-cert:       [mandatory]  [single]     [primary/look-up key]
+# method:         [generated]  [single]     [ ]
+# owner:          [generated]  [multiple]   [ ]
+# fingerpr:       [generated]  [single]     [inverse key]
+# certif:         [mandatory]  [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# admin-c:        [optional]   [multiple]   [inverse key]
+# tech-c:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary',   ['key_cert'] );
+__PACKAGE__->attributes( 'mandatory', [ 'key_cert', 'certif', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'method', 'owner', 'fingerpr', 'org', 'remarks', 'notify', 'admin_c', 'tech_c' ] );
+__PACKAGE__->attributes( 'single', [ 'key_cert', 'method', 'fingerpr', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'owner', 'certif', 'org', 'remarks', 'notify', 'admin_c', 'tech_c', 'mnt_by', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::KeyCert::AFRINIC - an object representation of the RPSL KeyCert block
+
+=head1 DESCRIPTION
+
+A key-cert object is a database public key certificate that is stored
+on the server and may be used with a mntner object for authentication
+when performing updates. Currently only PGP keys are supported.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::InetRtr class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<key_cert( [$key_cert] )>
+
+Accessor to the key_cert attribute.
+Accepts an optional key_cert value, always return the current key_cert value.
+
+For PGP KeyCert objects, the value of the key_cert attribute must be
+PGP-"key-id". These keys are compliant with the Open PGP Internet Standard.
+
+For X.509 KeyCert objects, the database software assigns this value as
+X.509-n. Here, 'n' is the next available number assigned by the software. If
+you want to create an X.509 KeyCert object, you should specify the value as
+AUTO-xx. If you delete an X.509 KeyCert object, it is not possible to
+recreate it with the same name.
+
+=head2 B<method( [$method] )>
+
+Accessor to the method attribute.
+Accepts an optional method, always return the current method value.
+
+The method attribute is generated by the software. 
+It is not necessary to include this attribute when you create or
+modify this object. If it is supplied, the software will check the value.
+If necessary the software will replace the supplied value with generated
+value. In this case a warning is returned to the user.
+
+=head2 B<owner( [$owner] )>
+
+Accessor to the owner attribute.
+Accepts an optional owner to be added to the owner array,
+always return the current owner array.
+
+The owner attribute is generated by the software. 
+It is not necessary to include this attribute when you create or
+modify this object. If it is supplied, the software will check the value.
+If necessary the software will replace the supplied value with generated
+value. In this case a warning is returned to the user.
+
+=head2 B<fingerpr( [$fingerpr] )>
+
+Accessor to the fingerpr attribute.
+Accepts an optional fingerpr, always return the current fingerpr.
+
+The fingerpr attribute is generated by the software. 
+It is not necessary to include this attribute when you create or
+modify this object. If it is supplied, the software will check the value.
+If necessary the software will replace the supplied value with generated
+value. In this case a warning is returned to the user.
+
+=head2 B<certif( [$certif] )>
+
+Accessor to the certif attribute.
+Accepts an optional certif to be added to the certif array,
+always return the current certif array.
+
+The certif attribute contains the public key. The value of the public key
+should be supplied either using multiple certif attributes, or in one
+certif attribute split over several lines. In the first case, this is
+easily done by exporting the key from your local key ring in ASCII armored
+format and adding the string certif to the start of each line of the key.
+In the second case, line continuation should be used to represent an ASCII
+armored format of the key. All the lines of the exported key must be included,
+as well as the start/end markers and the empty line which separates the header
+from the key body.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or email address.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation entity this object is bound to.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should be
+sent.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact Person object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact Person or Role object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered Mntner used to authorize and authenticate changes to this
+object.
+
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -0,0 +1,208 @@
+ackage Net::Whois::Object::KeyCert::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t key-cert
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# key-cert:       [mandatory]  [single]     [primary/lookup key]
+# method:         [generated]  [single]     [ ]
+# owner:          [generated]  [multiple]   [ ]
+# fingerpr:       [generated]  [single]     [inverse key]
+# certif:         [mandatory]  [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# admin-c:        [optional]   [multiple]   [inverse key]
+# tech-c:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS3)
+
+__PACKAGE__->attributes( 'primary',   [ 'key_cert' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'key_cert', 'certif', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'method', 'owner', 'fingerpr', 'org', 'remarks', 'notify', 'admin_c', 'tech_c' ] );
+__PACKAGE__->attributes( 'single',    [ 'key_cert', 'method', 'fingerpr', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'owner', 'certif', 'org', 'remarks', 'notify', 'admin_c', 'tech_c', 'mnt_by', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::KeyCert::APNIC - an object representation of the RPSL KeyCert block
+
+=head1 DESCRIPTION
+
+A key-cert object is a database public key certificate that is stored
+on the server and may be used with a mntner object for authentication
+when performing updates. Currently only PGP keys are supported.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::InetRtr class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<key_cert( [$key_cert] )>
+
+Accessor to the key_cert attribute.
+Accepts an optional key_cert value, always return the current key_cert value.
+
+For PGP KeyCert objects, the value of the key_cert attribute must be
+PGP-"key-id". These keys are compliant with the Open PGP Internet Standard.
+
+For X.509 KeyCert objects, the database software assigns this value as
+X.509-n. Here, 'n' is the next available number assigned by the software. If
+you want to create an X.509 KeyCert object, you should specify the value as
+AUTO-xx. If you delete an X.509 KeyCert object, it is not possible to
+recreate it with the same name.
+
+=head2 B<method( [$method] )>
+
+Accessor to the method attribute.
+Accepts an optional method, always return the current method value.
+
+The method attribute is generated by the software. 
+It is not necessary to include this attribute when you create or
+modify this object. If it is supplied, the software will check the value.
+If necessary the software will replace the supplied value with generated
+value. In this case a warning is returned to the user.
+
+=head2 B<owner( [$owner] )>
+
+Accessor to the owner attribute.
+Accepts an optional owner to be added to the owner array,
+always return the current owner array.
+
+The owner attribute is generated by the software. 
+It is not necessary to include this attribute when you create or
+modify this object. If it is supplied, the software will check the value.
+If necessary the software will replace the supplied value with generated
+value. In this case a warning is returned to the user.
+
+=head2 B<fingerpr( [$fingerpr] )>
+
+Accessor to the fingerpr attribute.
+Accepts an optional fingerpr, always return the current fingerpr.
+
+The fingerpr attribute is generated by the software. 
+It is not necessary to include this attribute when you create or
+modify this object. If it is supplied, the software will check the value.
+If necessary the software will replace the supplied value with generated
+value. In this case a warning is returned to the user.
+
+=head2 B<certif( [$certif] )>
+
+Accessor to the certif attribute.
+Accepts an optional certif to be added to the certif array,
+always return the current certif array.
+
+The certif attribute contains the public key. The value of the public key
+should be supplied either using multiple certif attributes, or in one
+certif attribute split over several lines. In the first case, this is
+easily done by exporting the key from your local key ring in ASCII armored
+format and adding the string certif to the start of each line of the key.
+In the second case, line continuation should be used to represent an ASCII
+armored format of the key. All the lines of the exported key must be included,
+as well as the start/end markers and the empty line which separates the header
+from the key body.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or email address.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation entity this object is bound to.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should be
+sent.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact Person object. As more than one person
+often fulfills a role function, there may be more than one admin_c listed.
+
+An administrative contact (admin_c) must be someone who is physically
+located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact Person or Role object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered Mntner used to authorize and authenticate changes to this
+object.
+
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The database where the object is registered.
+
+=cut
+
+1;
@@ -0,0 +1,114 @@
+package Net::Whois::Object::Limerick::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t limerick -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# limerick:       [mandatory]  [single]     [primary/look-up key]
+# descr:          [optional]   [multiple]   [ ]
+# text:           [mandatory]  [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# author:         [mandatory]  [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['limerick'] );
+__PACKAGE__->attributes( 'mandatory', [ 'limerick', 'text', 'admin_c', 'author', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'descr', 'org', 'remarks', 'notify' ] );
+__PACKAGE__->attributes( 'single', [ 'limerick', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'text', 'org',  'admin_c', 'author', 'remarks', 'notify', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Limerick::AFRINIC - an object representation of the RPSL Limerick block
+
+=head1 DESCRIPTION
+
+The limerick object represents a humorous poem that has five lines and
+the rhyme scheme "aabba".
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Limerick::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+
+}
+
+=head2 B<limerick( [$limerick] )>
+
+Accessor to the limerick attribute.
+Accepts an optional value, always return the current limerick value.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr to be added to the descr array,
+always return the current descr array.
+
+=head2 B<text( [$text] )>
+
+Accessor to the text attribute.
+Accepts an optional text to be added to the text array,
+always return the current text array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<author( [$author] )>
+
+Accessor to the author attribute.
+Accepts an optional author to be added to the author array,
+always return the current author array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=cut
+
+1;
@@ -2,7 +2,7 @@ package Net::Whois::Object::Limerick;
 
 use base qw/Net::Whois::Object/;
 
-# RIPE : Deprecated
+# RIPE: Deprecated
 #
 #
 # limerick:      [mandatory]  [single]     [primary/look-up key]
@@ -0,0 +1,237 @@
+package Net::Whois::Object::Mntner::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t mntner -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# mntner:         [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [optional]   [multiple]   [inverse key]
+# upd-to:         [mandatory]  [multiple]   [inverse key]
+# mnt-nfy:        [optional]   [multiple]   [inverse key]
+# auth:           [mandatory]  [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# abuse-mailbox:  [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['mntner'] );
+__PACKAGE__->attributes( 'mandatory', [ 'mntner', 'descr', 'admin_c', 'upd_to', 'auth', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'org', 'tech_c', 'mnt_nfy', 'remarks', 'notify', 'abuse_mailbox' ] );
+__PACKAGE__->attributes( 'single', [ 'mntner', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'org', 'admin_c', 'tech_c', 'upd_to', 'mnt_nfy', 'auth', 'remarks', 'notify', 'abuse_mailbox', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Mntner::AFRINIC - an object representation of the RPSL Mntner block
+
+=head1 DESCRIPTION
+
+Objects in the RIPE Database may be protected using Mntner (pronounced
+"maintainer") objects.  A Mntner object specifies authentication
+information required to authorise creation, deletion or modification
+of the objects protected by the Mntner.
+
+Objects are protected by a Mntner, if they contain a reference to the Mntner
+in the object. This is done by including a mnt-by attribute. Other
+attributes offer hierarchical protection. The mnt-by attribute is mandatory
+in all object types. Most users set the mnt-by value in a Mntner to
+reference itself.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Mntner::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<mntner( [$mntner] )>
+
+Accessor to the mntner attribute.
+Accepts an optional mntner value to be added to the mntner array,
+always return the current mntner.
+
+The unique name of a mntner object. APNIC recommends the following formats:
+
+Maintainer for resource registrations:
+
+<maint>-<iso3166-code>-<organization>
+
+ EXAMPLE 
+ MAINT-WF-SPARKYNET
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+A short description of the mntner object and the name of the organization
+associated with it.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation this object is bound to.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact Person object. As more than one
+person often fulfills a role function, there may be more than one admin_c
+listed.
+
+An administrative contact (admin_c) must be someone who is
+physically located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact Person or Role object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<upd_to( [$upd_to] )>
+
+Accessor to the upd_to attribute.
+Accepts an optional upd_to value to be added to the upd_to array,
+always return the current upd_to array.
+
+The upd_to attribute specifies the email address to be notified when an
+attempt to update an object protected by this Mntner is unsuccessful.
+
+=head2 B<mnt_nfy( [$mnt_nfy] )>
+
+Accessor to the mnt_nfy attribute.
+Accepts an optional mnt_nfy value to be added to the mnt_nfy array,
+always return the current mnt_nfy array.
+
+The mnt_nfy attribute specifies the email address to be notified when an
+object protected by this Mntner is successfully updated.
+
+=head2 B<auth( [$auth] )>
+
+Accessor to the auth attribute.
+Accepts an optional auth value to be added to the auth array,
+always return the current auth array.
+
+The auth attribute defines an authentication scheme to be used. . Any of
+the current authentication schemes used by the RIPE Database are allowed.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be addedt to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or email address.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should
+be sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered Mntner used to authorize and authenticate changes to
+this object.
+
+Most users set the mnt-by value in a Mntner to reference itself.
+
+=head2 B<auth_override( [$auth_override] )>
+
+Accessor to the auth_override attribute.
+Accepts an optional auth_override, always return the current auth_override.
+
+Routing Policy System Security specification defines an auth_override attribute
+in the Mntner object template. Together with referral-by attribute, they allow 
+for a Mntner to be modified if it becomes unresponsive. 
+As this is not part of the core functionality of the RIPE Database, 
+it has not been implemented in the current version of the database.
+
+=head2 B<referral_by( [$referral_by] )>
+
+Accessor to the referral_by attribute.
+Accepts an optional referral_by, always return the current referral_by.
+
+Routing Policy System Security specification defines an auth_override attribute
+in the Mntner object template. Together with referral-by attribute, they allow 
+for a Mntner to be modified if it becomes unresponsive. 
+As this is not part of the core functionality of the RIPE Database, 
+it has not been implemented in the current version of the database.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The name of the database from which the data was obtained.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional value, always return the current 'country'.
+Two letter ISO 3166 code of the country or economy where the admin-c is based.
+
+Please use UPPERCASE letters.
+
+=head2 B<abuse_mailbox( [$abuse_mailbox] )>
+
+Accessor to the abuse_mailbox attribute.
+Accepts an optional abuse_mailbox value to be added to the abuse_mailbox array,
+always return the current abuse_mailbox array.
+
+=cut
+
+1;
@@ -0,0 +1,242 @@
+package Net::Whois::Object::Mntner::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t mntner
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# mntner:         [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# country:        [optional]   [single]     [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [optional]   [multiple]   [inverse key]
+# upd-to:         [mandatory]  [multiple]   [inverse key]
+# mnt-nfy:        [optional]   [multiple]   [inverse key]
+# auth:           [mandatory]  [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# abuse-mailbox:  [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# referral-by:    [mandatory]  [single]     [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS4)
+
+__PACKAGE__->attributes( 'primary',   [ 'mntner' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'mntner', 'descr', 'admin_c', 'upd_to', 'auth', 'mnt_by', 'referral_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'country', 'org', 'tech_c', 'mnt_nfy', 'remarks', 'notify', 'abuse_mailbox' ] );
+__PACKAGE__->attributes( 'single',    [ 'mntner', 'country', 'referral_by', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'org', 'admin_c', 'tech_c', 'upd_to', 'mnt_nfy', 'auth', 'remarks', 'notify', 'abuse_mailbox', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Mntner::APNIC - an object representation of the RPSL Mntner block
+
+=head1 DESCRIPTION
+
+Objects in the RIPE Database may be protected using Mntner (pronounced
+"maintainer") objects.  A Mntner object specifies authentication
+information required to authorise creation, deletion or modification
+of the objects protected by the Mntner.
+
+Objects are protected by a Mntner, if they contain a reference to the Mntner
+in the object. This is done by including a mnt-by attribute. Other
+attributes offer hierarchical protection. The mnt-by attribute is mandatory
+in all object types. Most users set the mnt-by value in a Mntner to
+reference itself.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Mntner::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<mntner( [$mntner] )>
+
+Accessor to the mntner attribute.
+Accepts an optional mntner value to be added to the mntner array,
+always return the current mntner.
+
+The unique name of a mntner object. APNIC recommends the following formats:
+
+Maintainer for resource registrations:
+
+<maint>-<iso3166-code>-<organization>
+
+ EXAMPLE 
+ MAINT-WF-SPARKYNET
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+A short description of the mntner object and the name of the organization
+associated with it.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org value to be added to the org array,
+always return the current org array.
+
+The organisation this object is bound to.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+The NIC-handle of an on-site contact Person object. As more than one
+person often fulfills a role function, there may be more than one admin_c
+listed.
+
+An administrative contact (admin_c) must be someone who is
+physically located at the site of the network.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+The NIC-handle of a technical contact Person or Role object.  As more than
+one person often fulfills a role function, there may be more than one tech_c
+listed.
+
+A technical contact (tech_c) must be a person responsible for the
+day-to-day operation of the network, but does not need to be
+physically located at the site of the network.
+
+=head2 B<upd_to( [$upd_to] )>
+
+Accessor to the upd_to attribute.
+Accepts an optional upd_to value to be added to the upd_to array,
+always return the current upd_to array.
+
+The upd_to attribute specifies the email address to be notified when an
+attempt to update an object protected by this Mntner is unsuccessful.
+
+=head2 B<mnt_nfy( [$mnt_nfy] )>
+
+Accessor to the mnt_nfy attribute.
+Accepts an optional mnt_nfy value to be added to the mnt_nfy array,
+always return the current mnt_nfy array.
+
+The mnt_nfy attribute specifies the email address to be notified when an
+object protected by this Mntner is successfully updated.
+
+=head2 B<auth( [$auth] )>
+
+Accessor to the auth attribute.
+Accepts an optional auth value to be added to the auth array,
+always return the current auth array.
+
+The auth attribute defines an authentication scheme to be used. . Any of
+the current authentication schemes used by the RIPE Database are allowed.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be addedt to the remarks array,
+always return the current remarks array.
+
+General remarks. May include a URL or email address.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+The email address to which notifications of changes to this object should
+be sent.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+Lists a registered Mntner used to authorize and authenticate changes to
+this object.
+
+Most users set the mnt-by value in a Mntner to reference itself.
+
+=head2 B<auth_override( [$auth_override] )>
+
+Accessor to the auth_override attribute.
+Accepts an optional auth_override, always return the current auth_override.
+
+Routing Policy System Security specification defines an auth_override attribute
+in the Mntner object template. Together with referral-by attribute, they allow 
+for a Mntner to be modified if it becomes unresponsive. 
+As this is not part of the core functionality of the RIPE Database, 
+it has not been implemented in the current version of the database.
+
+=head2 B<referral_by( [$referral_by] )>
+
+Accessor to the referral_by attribute.
+Accepts an optional referral_by, always return the current referral_by.
+
+Routing Policy System Security specification defines an auth_override attribute
+in the Mntner object template. Together with referral-by attribute, they allow 
+for a Mntner to be modified if it becomes unresponsive. 
+As this is not part of the core functionality of the RIPE Database, 
+it has not been implemented in the current version of the database.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+The email address of who last updated the database object and the date it
+occurred.
+
+Every time a change is made to a database object, this attribute will show
+the email address of the person who made those changes.
+Please use the address format specified in RFC 822 - Standard for
+the Format of ARPA Internet Text Message and provide the date
+format using one of the following two formats: YYYYMMDD or YYMMDD.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+The name of the database from which the data was obtained.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional value, always return the current 'country'.
+Two letter ISO 3166 code of the country or economy where the admin-c is based.
+
+Please use UPPERCASE letters.
+
+=head2 B<abuse_mailbox( [$abuse_mailbox] )>
+
+Accessor to the abuse_mailbox attribute.
+Accepts an optional abuse_mailbox value to be added to the abuse_mailbox array,
+always return the current abuse_mailbox array.
+
+=cut
+
+1;
@@ -0,0 +1,191 @@
+package Net::Whois::Object::Organisation::AFRINIC;
+
+use base qw/Net::Whois::Object::Organisation/;
+
+# whois -h whois.afrinic.net -t organisation
+# 
+# % This is the AfriNIC Whois server.
+# 
+# organisation:   [mandatory]  [single]     [primary/look-up key]
+# org-name:       [mandatory]  [single]     [lookup key]
+# org-type:       [mandatory]  [single]     [ ]
+# descr:          [optional]   [multiple]   [ ]
+# country:        [mandatory]  [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# address:        [mandatory]  [multiple]   [ ]
+# phone:          [optional]   [multiple]   [ ]
+# fax-no:         [optional]   [multiple]   [ ]
+# e-mail:         [mandatory]  [multiple]   [lookup key]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [optional]   [multiple]   [inverse key]
+# tech-c:         [optional]   [multiple]   [inverse key]
+# ref-nfy:        [optional]   [multiple]   [inverse key]
+# mnt-ref:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# abuse-mailbox:  [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary',   ['organisation'] );
+__PACKAGE__->attributes( 'mandatory', [ 'organisation', 'org_name', 'org_type', 'country', 'address', 'e_mail', 'mnt_ref', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'descr', 'remarks', 'phone', 'fax_no', 'org', 'admin_c', 'tech_c', 'ref_nfy', 'notify', 'abuse_mailbox' ] );
+__PACKAGE__->attributes( 'single', [ 'organisation', 'org_name', 'org_type', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'country', 'remarks', 'address', 'phone', 'fax_no', 'e_mail', 'org', 'admin_c', 'tech_c', 'ref_nfy', 'mnt_ref', 'notify','abuse_mailbox', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Organisation - an object representation of the RPSL Organisation block
+
+=head1 DESCRIPTION
+
+The organisation object is designed to provide an easy way of mapping resources to a particular organisaiton.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Organisation class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<organisation( [$organisation] )>
+
+Accessor to the organisation attribute.
+Accepts an optional organisation, always return the current organisation.
+
+=head2 B<org_name( [$org_name] )>
+
+Accessor to the org_name attribute.
+Accepts an optional org_name, always return the current org_name.
+
+=head2 B<org_type( [$org_type] )>
+
+Accessor to the org_type attribute.
+Accepts an optional org_type, always return the current org_type.
+
+Possible values are:
+IANA for Internet Assigned Numbers Authority, RIR for Regional Internet
+Registries, NIR for National Internet Registries, LIR for Local Internet
+Registries, and OTHER for all other organisations. 
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<address( [$address] )>
+
+Accessor to the address attribute.
+Accepts an optional address line to be added to the address array,
+always return the current address array.
+
+=head2 B<phone( [$phone] )>
+
+Accessor to the phone attribute.
+Accepts an optional phone number to be added to the phone array,
+always return the current phone array.
+
+=head2 B<fax_no( [$fax_no] )>
+
+Accessor to the fax_no attribute.
+Accepts an optional fax_no to be added to the fax_no array,
+always return the current fax_no array.
+
+=head2 B<e_mail( [$e_mail] )>
+
+Accessor to the e_mail attribute.
+Accepts an optional e_mail to be added to the e_mail array,
+always return the current e_mail array.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country to be added to the country array,
+always return the current country array.
+
+=head2 B<language( [$language] )>
+
+Accessor to the language attribute.
+Accepts an optional language to be added to the language array,
+always return the current language array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<ref_nfy( [$ref_nfy] )>
+
+Accessor to the ref_nfy attribute.
+Accepts an optional ref_nfy value to be added to the ref_nfy array,
+always return the current ref_nfy array.
+
+=head2 B<mnt_ref( [$mnt_ref] )>
+
+Accessor to the mnt_ref attribute.
+Accepts an optional mnt_ref value to be added to the mnt_ref array,
+always return the current mnt_ref array.
+
+=cut
+
+1;
@@ -0,0 +1,194 @@
+package Net::Whois::Object::Organisation::APNIC;
+
+use base qw/Net::Whois::Object::Organisation/;
+
+# whois -h whois.apnic.net -t organisation
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# organisation:   [mandatory]  [single]     [primary/lookup key]
+# org-name:       [mandatory]  [single]     [lookup key]
+# org-type:       [mandatory]  [single]     [ ]
+# descr:          [optional]   [multiple]   [ ]
+# country:        [optional]   [multiple]   [ ]
+# address:        [mandatory]  [multiple]   [ ]
+# phone:          [optional]   [multiple]   [ ]
+# fax-no:         [optional]   [multiple]   [ ]
+# e-mail:         [mandatory]  [multiple]   [lookup key]
+# geoloc:         [optional]   [single]     [ ]
+# language:       [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [optional]   [multiple]   [inverse key]
+# tech-c:         [optional]   [multiple]   [inverse key]
+# ref-nfy:        [optional]   [multiple]   [inverse key]
+# mnt-ref:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# abuse-mailbox:  [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS2)
+
+__PACKAGE__->attributes( 'primary',   [ 'organisation' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'organisation', 'org_name', 'org_type', 'address', 'e_mail', 'mnt_ref', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'descr', 'country', 'phone', 'fax_no', 'geoloc', 'language', 'org', 'admin_c', 'tech_c', 'ref_nfy', 'notify', 'abuse_mailbox' ] );
+__PACKAGE__->attributes( 'single',    [ 'organisation', 'org_name', 'org_type', 'geoloc', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'country', 'address', 'phone', 'fax_no', 'e_mail', 'language', 'org', 'admin_c', 'tech_c', 'ref_nfy', 'mnt_ref', 'notify', 'abuse_mailbox', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Organisation - an object representation of the RPSL Organisation block
+
+=head1 DESCRIPTION
+
+The organisation object is designed to provide an easy way of mapping resources to a particular organisaiton.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Organisation class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<organisation( [$organisation] )>
+
+Accessor to the organisation attribute.
+Accepts an optional organisation, always return the current organisation.
+
+=head2 B<org_name( [$org_name] )>
+
+Accessor to the org_name attribute.
+Accepts an optional org_name, always return the current org_name.
+
+=head2 B<org_type( [$org_type] )>
+
+Accessor to the org_type attribute.
+Accepts an optional org_type, always return the current org_type.
+
+Possible values are:
+IANA for Internet Assigned Numbers Authority, RIR for Regional Internet
+Registries, NIR for National Internet Registries, LIR for Local Internet
+Registries, and OTHER for all other organisations. 
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<address( [$address] )>
+
+Accessor to the address attribute.
+Accepts an optional address line to be added to the address array,
+always return the current address array.
+
+=head2 B<phone( [$phone] )>
+
+Accessor to the phone attribute.
+Accepts an optional phone number to be added to the phone array,
+always return the current phone array.
+
+=head2 B<fax_no( [$fax_no] )>
+
+Accessor to the fax_no attribute.
+Accepts an optional fax_no to be added to the fax_no array,
+always return the current fax_no array.
+
+=head2 B<e_mail( [$e_mail] )>
+
+Accessor to the e_mail attribute.
+Accepts an optional e_mail to be added to the e_mail array,
+always return the current e_mail array.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country to be added to the country array,
+always return the current country array.
+
+=head2 B<language( [$language] )>
+
+Accessor to the language attribute.
+Accepts an optional language to be added to the language array,
+always return the current language array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<ref_nfy( [$ref_nfy] )>
+
+Accessor to the ref_nfy attribute.
+Accepts an optional ref_nfy value to be added to the ref_nfy array,
+always return the current ref_nfy array.
+
+=head2 B<mnt_ref( [$mnt_ref] )>
+
+Accessor to the mnt_ref attribute.
+Accepts an optional mnt_ref value to be added to the mnt_ref array,
+always return the current mnt_ref array.
+
+=cut
+
+1;
@@ -2,13 +2,13 @@ package Net::Whois::Object::Organisation;
 
 use base qw/Net::Whois::Object/;
 
-# From  : whois -t organisation
+# whois -h whois.ripe.net -t organisation
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
 # % The RIPE Database is subject to Terms and Conditions.
 # % See http://www.ripe.net/db/support/db-terms-conditions.pdf
-#
+# 
 # organisation:   [mandatory]  [single]     [primary/lookup key]
 # org-name:       [mandatory]  [single]     [lookup key]
 # org-type:       [mandatory]  [single]     [ ]
@@ -23,6 +23,7 @@ use base qw/Net::Whois::Object/;
 # org:            [optional]   [multiple]   [inverse key]
 # admin-c:        [optional]   [multiple]   [inverse key]
 # tech-c:         [optional]   [multiple]   [inverse key]
+# abuse-c:        [optional]   [single]     [inverse key]
 # ref-nfy:        [optional]   [multiple]   [inverse key]
 # mnt-ref:        [mandatory]  [multiple]   [inverse key]
 # notify:         [optional]   [multiple]   [inverse key]
@@ -30,12 +31,14 @@ use base qw/Net::Whois::Object/;
 # mnt-by:         [mandatory]  [multiple]   [inverse key]
 # changed:        [mandatory]  [multiple]   [ ]
 # source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the RIPE Database Query Service version 1.69 (WHOIS4)
 
-__PACKAGE__->attributes( 'primary',   ['organisation'] );
+__PACKAGE__->attributes( 'primary',   [ 'organisation' ] );
 __PACKAGE__->attributes( 'mandatory', [ 'organisation', 'org_name', 'org_type', 'address', 'e_mail', 'mnt_ref', 'mnt_by', 'changed', 'source' ] );
-__PACKAGE__->attributes( 'optional',  [ 'descr', 'remarks', 'phone', 'fax_no', 'geoloc', 'language', 'org', 'admin_c', 'tech_c', 'ref_nfy', 'notify', 'abuse_mailbox' ] );
-__PACKAGE__->attributes( 'single', [ 'organisation', 'org_name', 'org_type', 'geoloc','source' ] );
-__PACKAGE__->attributes( 'multiple', [ 'descr', 'remarks', 'address', 'phone', 'fax_no', 'e_mail','language', 'org', 'admin_c', 'tech_c', 'ref_nfy', 'mnt_ref', 'notify','abuse_mailbox', 'mnt_by', 'changed' ] );
+__PACKAGE__->attributes( 'optional',  [ 'descr', 'remarks', 'phone', 'fax_no', 'geoloc', 'language', 'org', 'abuse_c', 'admin_c', 'tech_c', 'ref_nfy', 'notify', 'abuse_mailbox' ] );
+__PACKAGE__->attributes( 'single',    [ 'organisation', 'org_name', 'org_type', 'geoloc', 'abuse_c', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'remarks', 'address', 'phone', 'fax_no', 'e_mail','language', 'org', 'admin_c', 'tech_c', 'ref_nfy', 'mnt_ref', 'notify','abuse_mailbox', 'mnt_by', 'changed' ] );
 
 =head1 NAME
 
@@ -77,7 +80,7 @@ Accepts an optional org_name, always return the current org_name.
 Accessor to the org_type attribute.
 Accepts an optional org_type, always return the current org_type.
 
-Possible values are :
+Possible values are:
 IANA for Internet Assigned Numbers Authority, RIR for Regional Internet
 Registries, NIR for National Internet Registries, LIR for Local Internet
 Registries, and OTHER for all other organisations. 
@@ -136,6 +139,12 @@ Accessor to the admin_c attribute.
 Accepts an optional contact to be added to the admin_c array,
 always return the current admin_c array.
 
+=head2 B<abuse_c( [$contact] )>
+
+Accessor to the abuse_c attribute.
+Accepts an optional contact to be added to the abuse_c array,
+always return the current abuse_c array.
+
 =head2 B<tech_c( [$contact] )>
 
 Accessor to the tech_c attribute.
@@ -0,0 +1,143 @@
+package Net::Whois::Object::PeeringSet::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t peering-set -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# peering-set:    [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# peering:        [optional]   [multiple]   [ ]
+# mp-peering:     [optional]   [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['peering_set'] );
+__PACKAGE__->attributes( 'mandatory', [ 'peering_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'peering', 'mp_peering', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single',    [ 'peering_set', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'peering', 'mp_peering', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::PeeringSet::AFRINIC - an object representation of the RPSL PeeringSet block
+
+=head1 DESCRIPTION
+
+A peering-set object defines a set of peerings that are listed in its
+"peering:" attributes.  The "peering-set:" attribute defines the name
+of the set.  It is an RPSL name that starts with "prng-".
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::PeeringSet::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<peering_set( [$peering_set] )>
+
+Accessor to the peering_set attribute (the name of the filter set).
+Accepts an optional peering_set, always return the current peering_set.
+
+The peering_set must begin with 'PRNG-'.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<peering( [$peering] )>
+
+Accessor to the peering attribute.
+Accepts an optional peering value to be added to the peering array,
+always return the current peering array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+        always return the current 'mnt_by' array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<mp_peering( [$mp_peering] )>
+
+Accessor to the mp_peering attribute.
+Accepts an optional mp_peering value to be added to the mp_peering array,
+always return the current mp_peering array.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=cut
+
+1;
@@ -0,0 +1,147 @@
+package Net::Whois::Object::PeeringSet::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t peering-set
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# peering-set:    [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# peering:        [optional]   [multiple]   [ ]
+# mp-peering:     [optional]   [multiple]   [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS1)
+
+
+__PACKAGE__->attributes( 'primary',   [ 'peering_set' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'peering_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'peering', 'mp_peering', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single',    [ 'peering_set', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'peering', 'mp_peering', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::PeeringSet::APNIC - an object representation of the RPSL PeeringSet block
+
+=head1 DESCRIPTION
+
+A peering-set object defines a set of peerings that are listed in its
+"peering:" attributes.  The "peering-set:" attribute defines the name
+of the set.  It is an RPSL name that starts with "prng-".
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::PeeringSet::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<peering_set( [$peering_set] )>
+
+Accessor to the peering_set attribute (the name of the filter set).
+Accepts an optional peering_set, always return the current peering_set.
+
+The peering_set must begin with 'PRNG-'.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<peering( [$peering] )>
+
+Accessor to the peering attribute.
+Accepts an optional peering value to be added to the peering array,
+always return the current peering array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+        always return the current 'mnt_by' array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<mp_peering( [$mp_peering] )>
+
+Accessor to the mp_peering attribute.
+Accepts an optional mp_peering value to be added to the mp_peering array,
+always return the current mp_peering array.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=cut
+
+1;
@@ -5,7 +5,7 @@ use base qw/Net::Whois::Object/;
 # http://www.ripe.net/data-tools/support/documentation/update-ref-manual#section-19
 # http://www.apnic.net/apnic-info/whois_search/using-whois/guide/peering-set
 #
-# From : whois -t peering-set 
+# From: whois -t peering-set 
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
@@ -0,0 +1,141 @@
+package Net::Whois::Object::Person::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t person -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# person:         [mandatory]  [single]     [lookup key]
+# address:        [mandatory]  [multiple]   [ ]
+# phone:          [mandatory]  [multiple]   [ ]
+# fax-no:         [optional]   [multiple]   [ ]
+# e-mail:         [mandatory]  [multiple]   [lookup key]
+# org:            [optional]   [multiple]   [inverse key]
+# nic-hdl:        [mandatory]  [single]     [primary/look-up key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# abuse-mailbox:  [optional]   [multiple]   [inverse key]
+# mnt-by:         [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['nic_hdl'] );
+__PACKAGE__->attributes( 'mandatory', [ 'person', 'address', 'phone', 'email', 'nic_hdl', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'fax_no', 'org', 'remarks', 'notify', 'abuse_mailbox', 'mnt_by' ] );
+__PACKAGE__->attributes( 'single', [ 'person', 'nic_hdl', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'address', 'phone', 'fax_no', 'e_mail', 'org', 'remarks', 'notify', 'abuse_mailbox', 'mnt_by', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::Person::AFRINIC - an object representation of the RPSL Person block
+
+=head1 DESCRIPTION
+
+A person object contains information about technical or administrative
+contact responsible for the object where it is referenced. Once the
+object is created, the value of the "person:" attribute cannot be
+changed.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Person::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<person( [$person] )>
+
+Accessor to the person attribute.
+Accepts an optional person, always return the current person.
+
+=head2 B<address( [$address] )>
+
+Accessor to the address attribute.
+Accepts an optional address line to be added to the address array,
+always return the current address array.
+
+=head2 B<phone( [$phone] )>
+
+Accessor to the phone attribute.
+Accepts an optional phone number to be added to the phone array,
+always return the current phone array.
+
+=head2 B<fax_no( [$fax_no] )>
+
+Accessor to the fax_no attribute.
+Accepts an optional fax_no to be added to the fax_no array,
+always return the current fax_no array.
+
+=head2 B<e_mail( [$e_mail] )>
+
+Accessor to the e_mail attribute.
+Accepts an optional e_mail to be added to the e_mail array,
+always return the current e_mail array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org array.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<nic_hdl( [$nic_hdl] )>
+
+Accessor to the nic_hdl attribute.
+Accepts an optional nic_hdl, always return the current nic_hdl.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<abuse_mailbox( [$abuse_mailbox] )>
+
+Accessor to the abuse_mailbox attribute.
+Accepts an optional abuse_mailbox value to be added to the abuse_mailbox array,
+always return the current abuse_mailbox array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=cut
+
+1;
@@ -0,0 +1,145 @@
+package Net::Whois::Object::Person::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t person
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# person:         [mandatory]  [single]     [lookup key]
+# address:        [mandatory]  [multiple]   [ ]
+# country:        [mandatory]  [single]     [ ]
+# phone:          [mandatory]  [multiple]   [ ]
+# fax-no:         [optional]   [multiple]   [ ]
+# e-mail:         [mandatory]  [multiple]   [lookup key]
+# org:            [optional]   [multiple]   [inverse key]
+# nic-hdl:        [mandatory]  [single]     [primary/lookup key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# abuse-mailbox:  [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS1)
+
+__PACKAGE__->attributes( 'primary',   [ 'nic_hdl' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'person', 'address', 'country', 'phone', 'email', 'nic_hdl', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'fax_no', 'org', 'remarks', 'notify', 'abuse_mailbox' ] );
+__PACKAGE__->attributes( 'single',    [ 'person', 'country', 'nic_hdl', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'address', 'phone', 'fax_no', 'e_mail', 'org', 'remarks', 'notify', 'abuse_mailbox', 'mnt_by', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::Person::APNIC - an object representation of the RPSL Person block
+
+=head1 DESCRIPTION
+
+A person object contains information about technical or administrative
+contact responsible for the object where it is referenced. Once the
+object is created, the value of the "person:" attribute cannot be
+changed.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Person::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<person( [$person] )>
+
+Accessor to the person attribute.
+Accepts an optional person, always return the current person.
+
+=head2 B<address( [$address] )>
+
+Accessor to the address attribute.
+Accepts an optional address line to be added to the address array,
+always return the current address array.
+
+=head2 B<phone( [$phone] )>
+
+Accessor to the phone attribute.
+Accepts an optional phone number to be added to the phone array,
+always return the current phone array.
+
+=head2 B<fax_no( [$fax_no] )>
+
+Accessor to the fax_no attribute.
+Accepts an optional fax_no to be added to the fax_no array,
+always return the current fax_no array.
+
+=head2 B<e_mail( [$e_mail] )>
+
+Accessor to the e_mail attribute.
+Accepts an optional e_mail to be added to the e_mail array,
+always return the current e_mail array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org array.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<nic_hdl( [$nic_hdl] )>
+
+Accessor to the nic_hdl attribute.
+Accepts an optional nic_hdl, always return the current nic_hdl.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<abuse_mailbox( [$abuse_mailbox] )>
+
+Accessor to the abuse_mailbox attribute.
+Accepts an optional abuse_mailbox value to be added to the abuse_mailbox array,
+always return the current abuse_mailbox array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=cut
+
+1;
@@ -5,7 +5,7 @@ use base qw/Net::Whois::Object/;
 # http://www.ripe.net/data-tools/support/documentation/update-ref-manual#section-20
 # http://www.apnic.net/apnic-info/whois_search/using-whois/guide/person
 #
-# From :  whois -t person
+# From:  whois -t person
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
@@ -0,0 +1,121 @@
+package Net::Whois::Object::Poem::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t poem
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# poem:           [mandatory]  [single]     [primary/lookup key]
+# descr:          [optional]   [multiple]   [ ]
+# form:           [mandatory]  [single]     [inverse key]
+# text:           [mandatory]  [multiple]   [ ]
+# author:         [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [single]     [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS1)
+
+__PACKAGE__->attributes( 'primary',   [ 'poem' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'poem', 'form', 'text', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'descr', 'author', 'remarks', 'notify' ] );
+__PACKAGE__->attributes( 'single',    [ 'poem',  'form', 'mnt_by', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'text', 'author', 'remarks', 'notify', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::Poem::APNIC - an object representation of the RPSL Poem block
+
+=head1 DESCRIPTION
+
+The poem object contains a poem that is submitted by a user. This object is
+included in the database to show that engineers do have a sense of humour.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Poem::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<text( [$text] )>
+
+Accessor to the text attribute.
+Accepts an optional text line to be added to the text array,
+always return the current text array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<author( [$author] )>
+
+Accessor to the author attribute.
+Accepts an optional author to be added to the author array,
+always return the current author array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<form( [$form] )>
+
+Accessor to the form attribute.
+Accepts an optional form, always return the current form.
+This attribute specifies the identifier of a registered poem type.
+
+=head2 B<poem( [$poem] )>
+
+Accessor to the poem attribute.
+Accepts an optional poem, always return the current poem.
+
+=cut
+
+1;
@@ -17,11 +17,11 @@ use base qw/Net::Whois::Object/;
 # changed:      [mandatory]     [multiple]  [ ]
 # source:       [mandatory]     [single]    [ ]
 #
-__PACKAGE__->attributes( 'primary', ['poem'] );
+__PACKAGE__->attributes( 'primary',   [ 'poem' ] );
 __PACKAGE__->attributes( 'mandatory', [ 'poem', 'form', 'text', 'author', 'admin_c', 'mnt_by', 'changed', 'source' ] );
-__PACKAGE__->attributes( 'optional', [ 'descr', 'remarks', 'notify' ] );
-__PACKAGE__->attributes( 'single',    [ 'poem',  'form',    'source' ] );
-__PACKAGE__->attributes( 'multiple',  [ 'descr', 'text',    'admin_c', 'author', 'remarks', 'notify', 'mnt_by', 'changed' ] );
+__PACKAGE__->attributes( 'optional',  [ 'descr', 'remarks', 'notify' ] );
+__PACKAGE__->attributes( 'single',    [ 'poem',  'form', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'text', 'admin_c', 'author', 'remarks', 'notify', 'mnt_by', 'changed' ] );
 
 
 =head1 NAME
@@ -0,0 +1,100 @@
+package Net::Whois::Object::PoeticForm::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t poetic-form
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# poetic-form:    [mandatory]  [single]     [primary/lookup key]
+# descr:          [optional]   [multiple]   [ ]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS1)
+
+__PACKAGE__->attributes( 'primary',   [ 'poetic_form' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'poetic_form', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'descr', 'remarks', 'notify' ] );
+__PACKAGE__->attributes( 'single',    [ 'poetic_form', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'admin_c', 'remarks', 'notify', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::PoeticForm::APNIC - an object representation of the RPSL PoeticForm block
+
+=head1 DESCRIPTION
+
+The poetic_form object contains a poetic_form that is submitted by a user. This object is
+included in the database to show that engineers do have a sense of humour.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::PoeticForm::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<poetic_form( [$poetic_form] )>
+
+Accessor to the poetic_form attribute.
+Accepts an optional poetic_form, always return the current poetic_form.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=cut
+
+1;
@@ -0,0 +1,160 @@
+package Net::Whois::Object::Role::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t role -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# role:           [mandatory]  [single]     [lookup key]
+# address:        [mandatory]  [multiple]   [ ]
+# phone:          [optional]   [multiple]   [ ]
+# fax-no:         [optional]   [multiple]   [ ]
+# e-mail:         [mandatory]  [multiple]   [lookup key]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# nic-hdl:        [mandatory]  [single]     [primary/look-up key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# abuse-mailbox:  [optional]   [multiple]   [inverse key]
+# mnt-by:         [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+
+__PACKAGE__->attributes( 'primary',   [ 'nic_hdl' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'role', 'address', 'e_mail', 'admin_c', 'tech_c', 'nic_hdl', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'phone', 'fax_no', 'org', 'remarks', 'notify', 'abuse_mailbox', 'mnt_by' ] );
+__PACKAGE__->attributes( 'single',    [ 'role', 'nic_hdl', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'address', 'e_mail', 'org', 'tech_c', 'admin_c', 'changed', 'phone', 'fax_no', 'trouble', 'remarks', 'notify', 'mnt_by', 'abuse_mailbox' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::Role::AFRINIC - an object representation of the RPSL Role block
+
+=head1 DESCRIPTION
+
+The role class is similar to the person class.  However, instead of
+describing a human being, it describes a role performed by one or more
+human beings.  Examples include help desks, network monitoring
+centres, system administrators, etc.  A role object is particularly
+useful since often a person performing a role may change; however the
+role itself remains. The "nic-hdl:" attributes of the person and role
+classes share the same name space. Once the object is created, the
+value of the "role:" attribute cannot be changed.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Role::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<role( [$role] )>
+
+Accessor to the role attribute.
+Accepts an optional role, always return the current role.
+
+=head2 B<address( [$address] )>
+
+Accessor to the address attribute.
+Accepts an optional address line to be added to the address array,
+always return the current address array.
+
+=head2 B<phone( [$phone] )>
+
+Accessor to the phone attribute.
+Accepts an optional phone to be added to the phone array,
+always return the current phone array.
+
+=head2 B<fax_no( [$fax_no] )>
+
+Accessor to the fax_no attribute.
+Accepts an optional fax_no to be added to the fax_no array,
+always return the current fax_no array.
+
+=head2 B<e_mail( [$e_mail] )>
+
+Accessor to the e_mail attribute.
+Accepts an optional e_mail to be added to the e_mail array,
+always return the current e_mail array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<trouble( [$trouble] )>
+
+Accessor to the trouble attribute.
+Accepts an optional trouble value to be added to the trouble array,
+always return the current trouble array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<nic_hdl( [$nic_hdl] )>
+
+Accessor to the nic_hdl attribute.
+Accepts an optional nic_hdl, always return the current nic_hdl.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=cut
+
+1;
@@ -0,0 +1,163 @@
+package Net::Whois::Object::Role::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t role
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# role:           [mandatory]  [single]     [lookup key]
+# address:        [mandatory]  [multiple]   [ ]
+# country:        [mandatory]  [single]     [ ]
+# phone:          [mandatory]  [multiple]   [ ]
+# fax-no:         [optional]   [multiple]   [ ]
+# e-mail:         [mandatory]  [multiple]   [lookup key]
+# org:            [optional]   [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# nic-hdl:        [mandatory]  [single]     [primary/lookup key]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# abuse-mailbox:  [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS1)
+
+__PACKAGE__->attributes( 'primary',   [ 'nic_hdl' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'role', 'address', 'country', 'phone', 'e_mail', 'admin_c', 'tech_c', 'nic_hdl', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'fax_no', 'org', 'remarks', 'notify', 'abuse_mailbox' ] );
+__PACKAGE__->attributes( 'single',    [ 'role', 'country', 'nic_hdl', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'address', 'phone', 'fax_no', 'e_mail', 'org', 'admin_c', 'tech_c', 'remarks', 'notify', 'abuse_mailbox', 'mnt_by', 'changed' ] );
+
+
+=head1 NAME
+
+Net::Whois::Object::Role::APNIC - an object representation of the RPSL Role block
+
+=head1 DESCRIPTION
+
+The role class is similar to the person class.  However, instead of
+describing a human being, it describes a role performed by one or more
+human beings.  Examples include help desks, network monitoring
+centres, system administrators, etc.  A role object is particularly
+useful since often a person performing a role may change; however the
+role itself remains. The "nic-hdl:" attributes of the person and role
+classes share the same name space. Once the object is created, the
+value of the "role:" attribute cannot be changed.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Role::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<role( [$role] )>
+
+Accessor to the role attribute.
+Accepts an optional role, always return the current role.
+
+=head2 B<address( [$address] )>
+
+Accessor to the address attribute.
+Accepts an optional address line to be added to the address array,
+always return the current address array.
+
+=head2 B<phone( [$phone] )>
+
+Accessor to the phone attribute.
+Accepts an optional phone to be added to the phone array,
+always return the current phone array.
+
+=head2 B<fax_no( [$fax_no] )>
+
+Accessor to the fax_no attribute.
+Accepts an optional fax_no to be added to the fax_no array,
+always return the current fax_no array.
+
+=head2 B<e_mail( [$e_mail] )>
+
+Accessor to the e_mail attribute.
+Accepts an optional e_mail to be added to the e_mail array,
+always return the current e_mail array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<trouble( [$trouble] )>
+
+Accessor to the trouble attribute.
+Accepts an optional trouble value to be added to the trouble array,
+always return the current trouble array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<nic_hdl( [$nic_hdl] )>
+
+Accessor to the nic_hdl attribute.
+Accepts an optional nic_hdl, always return the current nic_hdl.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=cut
+
+1;
@@ -0,0 +1,220 @@
+package Net::Whois::Object::Route::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t route -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# route:          [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# origin:         [mandatory]  [single]     [primary/inverse key]
+# holes:          [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# member-of:      [optional]   [multiple]   [ ]
+# inject:         [optional]   [multiple]   [ ]
+# aggr-mtd:       [optional]   [single]     [ ]
+# aggr-bndry:     [optional]   [single]     [ ]
+# export-comps:   [optional]   [single]     [ ]
+# components:     [optional]   [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary',   ['route'] );
+__PACKAGE__->attributes( 'mandatory', [ 'route', 'descr', 'origin', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'holes', 'org', 'member_of', 'inject', 'aggr_mtd', 'aggr_bndry', 'export_comps', 'components', 'remarks', 'notify', 'mnt_lower', 'mnt_routes' ] );
+__PACKAGE__->attributes( 'single', [ 'route', 'origin', 'aggr_mtd', 'aggr_bndry', 'export_comps', 'components', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'holes', 'org', 'member_of', 'inject', 'remarks', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Route::AFRINIC - an object representation of the RPSL Route block
+
+=head1 DESCRIPTION
+
+Route objects are used to help configure your network's routers. Route objects, 
+in combination with the aut-num and other related objects, can be used to
+describe your IPv4 routing policy in a compact form. This can help your
+network identify routing policy errors and omissions more easily than by
+reading long configuration files.
+
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Route::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+}
+
+=head2 B<route( [$route] )>
+
+Accessor to the route attribute.
+Accepts an optional route, always return the current route.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<origin( [$origin] )>
+
+Accessor to the origin attribute.
+Accepts an optional origin, always return the current origin.
+
+=head2 B<pingable( [$pingable] )>
+
+Accessor to the pingable attribute.
+Accepts an optional pingable line to be added to the pingable array,
+always return the current pingable array.
+
+An IPv4 or an IPv6 address allowing a network operator to advertise an IP address of a node
+that should be reachable from outside networks. This node can be
+used as a destination address for diagnostic tests.
+The IP address must be within the address range of the prefix
+containing this attribute.
+
+=head2 B<ping_hdl( [$ping_hdl] )>
+
+Accessor to the ping_hdl attribute.
+Accepts an optional ping_hdl line to be added to the ping_hdl array,
+always return the current ping_hdl array.
+
+References a person or role capable of responding to queries
+concerning the IP address(es) specified in the 'pingable'
+attribute.
+
+=head2 B<holes( [$hole] )>
+
+Accessor to the holes attribute.
+Accepts an optional hole to be added to the holes array,
+always return the current holes array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<member_of( [$member_of] )>
+
+Accessor to the member_of attribute.
+Accepts an optional member_of value to be added to the member_of array,
+always return the current member_of array.
+
+=head2 B<inject( [$inject] )>
+
+Accessor to the inject attribute.
+Accepts an optional inject value to be added to the inject array,
+always return the current inject array.
+
+=head2 B<aggr_mtd( [$aggr_mtd] )>
+
+Accessor to the aggr_mtd attribute.
+Accepts an optional aggr_mtd value to be added to the aggr_mtd array,
+always return the current aggr_mtd.
+
+=head2 B<aggr_bndry( [$aggr_bndry] )>
+
+Accessor to the aggr_bndry attribute.
+Accepts an optional aggr_bndry value to be added to the aggr_bndry array,
+always return the current aggr_bndry.
+
+=head2 B<export_comps( [$export_comp] )>
+
+Accessor to the export_comps attribute.
+Accepts an optional export_comp value to be added the export_comps array,
+always return the current export_comps.
+
+=head2 B<components( [$component] )>
+
+Accessor to the components attribute.
+Accepts an optional component to be added to the components array,
+always return the current components.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current 'remarks' array.
+
+=head2 B<cross_mnt( [$cross_mnt] )>
+
+Accessor to the cross_mnt attribute.
+Accepts an optional cross_mnt value to be added to the cross_mnt array,
+always return the current cross_mnt array.
+
+=head2 B<cross_nfy( [$cross_nfy] )>
+
+Accessor to the cross_nfy attribute.
+Accepts an optional cross_nfy value to be added to the cross_nfy array,
+always return the current cross_nfy array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=head2 B<mnt_routes( [$mnt_route] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_route to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country, always return the current country.
+Two letter ISO 3166 code of the country or economy where the admin-c is based.
+
+Please use UPPERCASE letters.
+
+=cut
+
+1;
@@ -0,0 +1,224 @@
+package Net::Whois::Object::Route::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t route
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# route:          [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# origin:         [mandatory]  [single]     [primary/inverse key]
+# holes:          [optional]   [multiple]   [ ]
+# country:        [optional]   [single]     [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# member-of:      [optional]   [multiple]   [inverse key]
+# inject:         [optional]   [multiple]   [ ]
+# aggr-mtd:       [optional]   [single]     [ ]
+# aggr-bndry:     [optional]   [single]     [ ]
+# export-comps:   [optional]   [single]     [ ]
+# components:     [optional]   [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS3)
+
+__PACKAGE__->attributes( 'primary',   [ 'route' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'route', 'descr', 'origin', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'holes', 'country', 'org', 'member_of', 'inject', 'aggr_mtd', 'aggr_bndry', 'export_comps', 'components', 'remarks', 'notify', 'mnt_lower', 'mnt_routes' ] );
+__PACKAGE__->attributes( 'single',    [ 'route', 'origin', 'country', 'aggr_mtd', 'aggr_bndry', 'export_comps', 'components', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'holes', 'org', 'member_of', 'inject', 'remarks', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Route::APNIC - an object representation of the RPSL Route block
+
+=head1 DESCRIPTION
+
+Route objects are used to help configure your network's routers. Route objects, 
+in combination with the aut-num and other related objects, can be used to
+describe your IPv4 routing policy in a compact form. This can help your
+network identify routing policy errors and omissions more easily than by
+reading long configuration files.
+
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Route::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+}
+
+=head2 B<route( [$route] )>
+
+Accessor to the route attribute.
+Accepts an optional route, always return the current route.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<origin( [$origin] )>
+
+Accessor to the origin attribute.
+Accepts an optional origin, always return the current origin.
+
+=head2 B<pingable( [$pingable] )>
+
+Accessor to the pingable attribute.
+Accepts an optional pingable line to be added to the pingable array,
+always return the current pingable array.
+
+An IPv4 or an IPv6 address allowing a network operator to advertise an IP address of a node
+that should be reachable from outside networks. This node can be
+used as a destination address for diagnostic tests.
+The IP address must be within the address range of the prefix
+containing this attribute.
+
+=head2 B<ping_hdl( [$ping_hdl] )>
+
+Accessor to the ping_hdl attribute.
+Accepts an optional ping_hdl line to be added to the ping_hdl array,
+always return the current ping_hdl array.
+
+References a person or role capable of responding to queries
+concerning the IP address(es) specified in the 'pingable'
+attribute.
+
+=head2 B<holes( [$hole] )>
+
+Accessor to the holes attribute.
+Accepts an optional hole to be added to the holes array,
+always return the current holes array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<member_of( [$member_of] )>
+
+Accessor to the member_of attribute.
+Accepts an optional member_of value to be added to the member_of array,
+always return the current member_of array.
+
+=head2 B<inject( [$inject] )>
+
+Accessor to the inject attribute.
+Accepts an optional inject value to be added to the inject array,
+always return the current inject array.
+
+=head2 B<aggr_mtd( [$aggr_mtd] )>
+
+Accessor to the aggr_mtd attribute.
+Accepts an optional aggr_mtd value to be added to the aggr_mtd array,
+always return the current aggr_mtd.
+
+=head2 B<aggr_bndry( [$aggr_bndry] )>
+
+Accessor to the aggr_bndry attribute.
+Accepts an optional aggr_bndry value to be added to the aggr_bndry array,
+always return the current aggr_bndry.
+
+=head2 B<export_comps( [$export_comp] )>
+
+Accessor to the export_comps attribute.
+Accepts an optional export_comp value to be added the export_comps array,
+always return the current export_comps.
+
+=head2 B<components( [$component] )>
+
+Accessor to the components attribute.
+Accepts an optional component to be added to the components array,
+always return the current components.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current 'remarks' array.
+
+=head2 B<cross_mnt( [$cross_mnt] )>
+
+Accessor to the cross_mnt attribute.
+Accepts an optional cross_mnt value to be added to the cross_mnt array,
+always return the current cross_mnt array.
+
+=head2 B<cross_nfy( [$cross_nfy] )>
+
+Accessor to the cross_nfy attribute.
+Accepts an optional cross_nfy value to be added to the cross_nfy array,
+always return the current cross_nfy array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=head2 B<mnt_routes( [$mnt_route] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_route to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country, always return the current country.
+Two letter ISO 3166 code of the country or economy where the admin-c is based.
+
+Please use UPPERCASE letters.
+
+=cut
+
+1;
@@ -5,7 +5,7 @@ use base qw/Net::Whois::Object/;
 # http://www.ripe.net/data-tools/support/documentation/update-ref-manual#section-25
 # http://www.apnic.net/apnic-info/whois_search/using-whois/guide/route
 #
-# From : whois -t route
+# From: whois -t route
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
@@ -0,0 +1,206 @@
+package Net::Whois::Object::Route6::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t route6 -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# route6:         [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# origin:         [mandatory]  [single]     [primary/inverse key]
+# holes:          [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# member-of:      [optional]   [multiple]   [ ]
+# inject:         [optional]   [multiple]   [ ]
+# aggr-mtd:       [optional]   [single]     [ ]
+# aggr-bndry:     [optional]   [single]     [ ]
+# export-comps:   [optional]   [single]     [ ]
+# components:     [optional]   [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary',   ['route6'] );
+__PACKAGE__->attributes( 'mandatory', [ 'route6', 'descr', 'origin', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'holes', 'org', 'member_of', 'inject', 'aggr_mtd', 'aggr_bndry', 'export_comps', 'components', 'remarks', 'notify', 'mnt_lower', 'mnt_routes' ] );
+__PACKAGE__->attributes( 'single', [ 'route6', 'origin', 'aggr_mtd', 'aggr_bndry', 'export_comps', 'components', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'holes', 'org', 'member_of', 'inject', 'remarks', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Route6::AFRINIC - an object representation of the RPSL Route6 block
+
+=head1 DESCRIPTION
+
+Route6 objects are used to help configure your network's routers. Route6 objects,
+in combination with the aut-num and other related objects, can be used to
+describe your IPv6 routing policy in a compact form. This can help your
+network identify routing policy errors and omissions more easily than by
+reading long configuration files.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Route6::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<route6( [$route6] )>
+
+Accessor to the route6 attribute.
+Accepts an optional route6, always return the current route.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<origin( [$origin] )>
+
+Accessor to the origin attribute.
+Accepts an optional origin, always return the current origin.
+
+=head2 B<pingable( [$pingable] )>
+
+Accessor to the pingable attribute.
+Accepts an optional pingable line to be added to the pingable array,
+always return the current pingable array.
+
+An IPv4 or an IPv6 address allowing a network operator to advertise an IP address of a node
+that should be reachable from outside networks. This node can be
+used as a destination address for diagnostic tests.
+The IP address must be within the address range of the prefix
+containing this attribute.
+
+=head2 B<ping_hdl( [$ping_hdl] )>
+
+Accessor to the ping_hdl attribute.
+Accepts an optional ping_hdl line to be added to the ping_hdl array,
+always return the current ping_hdl array.
+
+References a person or role capable of responding to queries
+concerning the IP address(es) specified in the 'pingable'
+attribute.
+
+=head2 B<holes( [$hole] )>
+
+Accessor to the holes attribute.
+Accepts an optional hole to be added to the holes array,
+always return the current holes array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<member_of( [$member_of] )>
+
+Accessor to the member_of attribute.
+Accepts an optional member_of value to be added to the member_of array,
+always return the current member_of array.
+
+=head2 B<inject( [$inject] )>
+
+Accessor to the inject attribute.
+Accepts an optional inject value to be added to the inject array,
+always return the current inject array.
+
+=head2 B<aggr_mtd( [$aggr_mtd] )>
+
+Accessor to the aggr_mtd attribute.
+Accepts an optional aggr_mtd value to be added to the aggr_mtd array,
+always return the current aggr_mtd.
+
+=head2 B<aggr_bndry( [$aggr_bndry] )>
+
+Accessor to the aggr_bndry attribute.
+Accepts an optional aggr_bndry value to be added to the aggr_bndry array,
+always return the current aggr_bndry.
+
+=head2 B<export_comps( [$export_comp] )>
+
+Accessor to the export_comps attribute.
+Accepts an optional export_comp value to be added the export_comps array,
+always return the current export_comps.
+
+=head2 B<components( [$component] )>
+
+Accessor to the components attribute.
+Accepts an optional component to be added to the components array,
+always return the current components.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current 'remarks' array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=head2 B<mnt_routes( [$mnt_route] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_route to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country, always return the current country.
+Two letter ISO 3166 code of the country or economy where the admin-c is based.
+
+Please use UPPERCASE letters.
+
+=cut
+
+1;
@@ -0,0 +1,210 @@
+package Net::Whois::Object::Route6::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t route6
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# route6:         [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# origin:         [mandatory]  [single]     [primary/inverse key]
+# country:        [optional]   [single]     [ ]
+# holes:          [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# member-of:      [optional]   [multiple]   [inverse key]
+# inject:         [optional]   [multiple]   [ ]
+# aggr-mtd:       [optional]   [single]     [ ]
+# aggr-bndry:     [optional]   [single]     [ ]
+# export-comps:   [optional]   [single]     [ ]
+# components:     [optional]   [single]     [ ]
+# remarks:        [optional]   [multiple]   [ ]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# mnt-routes:     [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS2)
+
+__PACKAGE__->attributes( 'primary',   [ 'route6' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'route6', 'descr', 'origin', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'country', 'holes', 'org', 'member_of', 'inject', 'aggr_mtd', 'aggr_bndry', 'export_comps', 'components', 'remarks', 'notify', 'mnt_lower', 'mnt_routes' ] );
+__PACKAGE__->attributes( 'single',    [ 'route6', 'origin', 'country', 'aggr_mtd', 'aggr_bndry', 'export_comps', 'components', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'holes', 'org', 'member_of', 'inject', 'remarks', 'notify', 'mnt_lower', 'mnt_routes', 'mnt_by', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::Route6::APNIC - an object representation of the RPSL Route6 block
+
+=head1 DESCRIPTION
+
+Route6 objects are used to help configure your network's routers. Route6 objects,
+in combination with the aut-num and other related objects, can be used to
+describe your IPv6 routing policy in a compact form. This can help your
+network identify routing policy errors and omissions more easily than by
+reading long configuration files.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::Route6::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<route6( [$route6] )>
+
+Accessor to the route6 attribute.
+Accepts an optional route6, always return the current route.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<origin( [$origin] )>
+
+Accessor to the origin attribute.
+Accepts an optional origin, always return the current origin.
+
+=head2 B<pingable( [$pingable] )>
+
+Accessor to the pingable attribute.
+Accepts an optional pingable line to be added to the pingable array,
+always return the current pingable array.
+
+An IPv4 or an IPv6 address allowing a network operator to advertise an IP address of a node
+that should be reachable from outside networks. This node can be
+used as a destination address for diagnostic tests.
+The IP address must be within the address range of the prefix
+containing this attribute.
+
+=head2 B<ping_hdl( [$ping_hdl] )>
+
+Accessor to the ping_hdl attribute.
+Accepts an optional ping_hdl line to be added to the ping_hdl array,
+always return the current ping_hdl array.
+
+References a person or role capable of responding to queries
+concerning the IP address(es) specified in the 'pingable'
+attribute.
+
+=head2 B<holes( [$hole] )>
+
+Accessor to the holes attribute.
+Accepts an optional hole to be added to the holes array,
+always return the current holes array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<member_of( [$member_of] )>
+
+Accessor to the member_of attribute.
+Accepts an optional member_of value to be added to the member_of array,
+always return the current member_of array.
+
+=head2 B<inject( [$inject] )>
+
+Accessor to the inject attribute.
+Accepts an optional inject value to be added to the inject array,
+always return the current inject array.
+
+=head2 B<aggr_mtd( [$aggr_mtd] )>
+
+Accessor to the aggr_mtd attribute.
+Accepts an optional aggr_mtd value to be added to the aggr_mtd array,
+always return the current aggr_mtd.
+
+=head2 B<aggr_bndry( [$aggr_bndry] )>
+
+Accessor to the aggr_bndry attribute.
+Accepts an optional aggr_bndry value to be added to the aggr_bndry array,
+always return the current aggr_bndry.
+
+=head2 B<export_comps( [$export_comp] )>
+
+Accessor to the export_comps attribute.
+Accepts an optional export_comp value to be added the export_comps array,
+always return the current export_comps.
+
+=head2 B<components( [$component] )>
+
+Accessor to the components attribute.
+Accepts an optional component to be added to the components array,
+always return the current components.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current 'remarks' array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=head2 B<mnt_routes( [$mnt_route] )>
+
+Accessor to the mnt_routes attribute.
+Accepts an optional mnt_route to be added to the mnt_routes array,
+always return the current mnt_routes array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<country( [$country] )>
+
+Accessor to the country attribute.
+Accepts an optional country, always return the current country.
+Two letter ISO 3166 code of the country or economy where the admin-c is based.
+
+Please use UPPERCASE letters.
+
+=cut
+
+1;
@@ -0,0 +1,152 @@
+package Net::Whois::Object::RouteSet::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t route-set -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# route-set:      [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# members:        [optional]   [multiple]   [ ]
+# mp-members:     [optional]   [multiple]   [ ]
+# mbrs-by-ref:    [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['route_set'] );
+__PACKAGE__->attributes( 'mandatory', [ 'route_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'members', 'mp_members', 'mbrs_by_ref', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single', [ 'route_set', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'members', 'mp_members', 'mbrs_by_ref', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::RouteSet::AFRINIC - an object representation of the RPSL RouteSet block
+
+=head1 DESCRIPTION
+
+A route-set object defines a set of routes that can be represented by
+route objects or by address prefixes. In the first case, the set is
+populated by means of the "mbrs-by-ref:" attribute, in the latter, the
+members of the set are explicitly listed in the "members:"
+attribute. The "members:" attribute is a list of address prefixes or
+other route-set names.  Note that the route-set class is a set of
+route prefixes, not of database route objects.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::RouteSet::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+}
+
+=head2 B<route_set( [$route_set] )>
+
+Accessor to the route_set attribute.
+Accepts an optional route_set, always return the current route_set.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<members( [$members] )>
+
+Accessor to the members attribute.
+Accepts an optional members value to be added to the members array,
+always return the current members array.
+
+=head2 B<mbrs_by_ref( [$mbrs_by_ref] )>
+
+Accessor to the mbrs_by_ref attribute.
+Accepts an optional mbrs_by_ref to be added to the mbrs_by_ref array,
+        always return the current 'mbrs_by_ref' array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=head2 B<mp_members( [$mp_member] )>
+
+Accessor to the mp_members attribute.
+Accepts an optional mp_member to be added to the mp_members array,
+always return the current mp_members array.
+
+=cut
+
+1;
@@ -0,0 +1,155 @@
+package Net::Whois::Object::RouteSet::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t route-set
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# route-set:      [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# members:        [optional]   [multiple]   [ ]
+# mp-members:     [optional]   [multiple]   [ ]
+# mbrs-by-ref:    [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS2)
+ 
+__PACKAGE__->attributes( 'primary',   [ 'route_set' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'route_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'members', 'mp_members', 'mbrs_by_ref', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single',    [ 'route_set', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'members', 'mp_members', 'mbrs_by_ref', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::RouteSet::APNIC - an object representation of the RPSL RouteSet block
+
+=head1 DESCRIPTION
+
+A route-set object defines a set of routes that can be represented by
+route objects or by address prefixes. In the first case, the set is
+populated by means of the "mbrs-by-ref:" attribute, in the latter, the
+members of the set are explicitly listed in the "members:"
+attribute. The "members:" attribute is a list of address prefixes or
+other route-set names.  Note that the route-set class is a set of
+route prefixes, not of database route objects.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::RouteSet::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+
+    return $self;
+}
+
+=head2 B<route_set( [$route_set] )>
+
+Accessor to the route_set attribute.
+Accepts an optional route_set, always return the current route_set.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<members( [$members] )>
+
+Accessor to the members attribute.
+Accepts an optional members value to be added to the members array,
+always return the current members array.
+
+=head2 B<mbrs_by_ref( [$mbrs_by_ref] )>
+
+Accessor to the mbrs_by_ref attribute.
+Accepts an optional mbrs_by_ref to be added to the mbrs_by_ref array,
+        always return the current 'mbrs_by_ref' array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by] )>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<mnt_lower( [$mnt_lower] )>
+
+Accessor to the mnt_lower attribute.
+Accepts an optional mnt_lower value to be added to the mnt_lower array,
+always return the current mnt_lower array.
+
+=head2 B<mp_members( [$mp_member] )>
+
+Accessor to the mp_members attribute.
+Accepts an optional mp_member to be added to the mp_members array,
+always return the current mp_members array.
+
+=cut
+
+1;
@@ -5,7 +5,7 @@ use base qw/Net::Whois::Object/;
 # http://www.ripe.net/data-tools/support/documentation/update-ref-manual#section-26
 # http://www.apnic.net/apnic-info/whois_search/using-whois/guide/route-set
 #
-# From : whois -t route-set
+# From: whois -t route-set
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
@@ -0,0 +1,154 @@
+package Net::Whois::Object::RtrSet::AFRINIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -t rtr-set -h whois.afrinic.net
+# % This is the AfriNIC Whois server.
+# 
+# rtr-set:        [mandatory]  [single]     [primary/look-up key]
+# descr:          [mandatory]  [multiple]   [ ]
+# members:        [optional]   [multiple]   [ ]
+# mp-members:     [optional]   [multiple]   [ ]
+# mbrs-by-ref:    [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+
+__PACKAGE__->attributes( 'primary', ['rtr_set'] );
+__PACKAGE__->attributes( 'mandatory', [ 'rtr_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional', [ 'members', 'mp_members', 'mbrs_by_ref', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single', [ 'rtr_set', 'source' ] );
+__PACKAGE__->attributes( 'multiple', [ 'descr', 'members', 'mp_members', 'mbrs_by_ref', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::RtrSet::AFRINIC - an object representation of the RPSL RtrSet block
+
+=head1 DESCRIPTION
+
+A rtr-set object defines a set of routers. A set may be described by
+the "members:" attribute, which is a list of inet-rtr names, IPv4
+addresses or other rtr-set names. A set may also be populated by means
+of the "mbrs-by-ref:" attribute, in which case it is represented by
+inet-rtr objects.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::RtrSet::AFRINIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<rtr_set( [$rtr_set] )>
+
+Accessor to the rtr_set attribute.
+Accepts an optional rtr_set, always return the current rtr_set.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<members( [$member] )>
+
+Accessor to the members attribute.
+Accepts an optional member to be added to the members array,
+always return the current members array.
+
+=head2 B<mbrs_by_ref( [$mbrs_by_ref] )>
+
+Accessor to the mbrs_by_ref attribute.
+Accepts an optional mbrs_by_ref value to be added to the mbrs_by_ref array,
+always return the current mbrs_by_ref array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by])>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<mp_members( [$mp_member] )>
+
+Accessor to the mp_members attribute.
+Accepts an optional mp_member to be added to the mp_members array,
+always return the current mp_members array.
+
+This attribute performs the same function as the members attribute above.
+The difference is that mp-members allows both IPv4 and IPv6 address families
+to be specified.
+
+Explicitly lists IPv4 or IPv6 'members' of the rtr-set can be:
+
+    * inet-rtr objects
+    * other rtr-set objects
+    * ipv4 address
+    * ipv6 address
+
+=cut
+
+1;
@@ -0,0 +1,157 @@
+package Net::Whois::Object::RtrSet::APNIC;
+
+use base qw/Net::Whois::Object/;
+
+# whois -h whois.apnic.net -t rtr-set
+# % [whois.apnic.net]
+# % Whois data copyright terms    http://www.apnic.net/db/dbcopyright.html
+# 
+# rtr-set:        [mandatory]  [single]     [primary/lookup key]
+# descr:          [mandatory]  [multiple]   [ ]
+# members:        [optional]   [multiple]   [ ]
+# mp-members:     [optional]   [multiple]   [ ]
+# mbrs-by-ref:    [optional]   [multiple]   [inverse key]
+# remarks:        [optional]   [multiple]   [ ]
+# org:            [optional]   [multiple]   [inverse key]
+# tech-c:         [mandatory]  [multiple]   [inverse key]
+# admin-c:        [mandatory]  [multiple]   [inverse key]
+# notify:         [optional]   [multiple]   [inverse key]
+# mnt-by:         [mandatory]  [multiple]   [inverse key]
+# mnt-lower:      [optional]   [multiple]   [inverse key]
+# changed:        [mandatory]  [multiple]   [ ]
+# source:         [mandatory]  [single]     [ ]
+# 
+# % This query was served by the APNIC Whois Service version 1.68.5 (WHOIS4)
+
+__PACKAGE__->attributes( 'primary',   [ 'rtr_set' ] );
+__PACKAGE__->attributes( 'mandatory', [ 'rtr_set', 'descr', 'tech_c', 'admin_c', 'mnt_by', 'changed', 'source' ] );
+__PACKAGE__->attributes( 'optional',  [ 'members', 'mp_members', 'mbrs_by_ref', 'remarks', 'org', 'notify', 'mnt_lower' ] );
+__PACKAGE__->attributes( 'single',    [ 'rtr_set', 'source' ] );
+__PACKAGE__->attributes( 'multiple',  [ 'descr', 'members', 'mp_members', 'mbrs_by_ref', 'remarks', 'org', 'tech_c', 'admin_c', 'notify', 'mnt_by', 'mnt_lower', 'changed' ] );
+
+=head1 NAME
+
+Net::Whois::Object::RtrSet::APNIC - an object representation of the RPSL RtrSet block
+
+=head1 DESCRIPTION
+
+A rtr-set object defines a set of routers. A set may be described by
+the "members:" attribute, which is a list of inet-rtr names, IPv4
+addresses or other rtr-set names. A set may also be populated by means
+of the "mbrs-by-ref:" attribute, in which case it is represented by
+inet-rtr objects.
+
+=head1 METHODS
+
+=head2 B<new( %options )>
+
+Constructor for the Net::Whois::Object::RtrSet::APNIC class
+
+=cut
+
+sub new {
+    my ( $class, @options ) = @_;
+
+    my $self = bless {}, $class;
+    $self->_init(@options);
+
+    return $self;
+}
+
+=head2 B<rtr_set( [$rtr_set] )>
+
+Accessor to the rtr_set attribute.
+Accepts an optional rtr_set, always return the current rtr_set.
+
+=head2 B<descr( [$descr] )>
+
+Accessor to the descr attribute.
+Accepts an optional descr line to be added to the descr array,
+always return the current descr array.
+
+=head2 B<members( [$member] )>
+
+Accessor to the members attribute.
+Accepts an optional member to be added to the members array,
+always return the current members array.
+
+=head2 B<mbrs_by_ref( [$mbrs_by_ref] )>
+
+Accessor to the mbrs_by_ref attribute.
+Accepts an optional mbrs_by_ref value to be added to the mbrs_by_ref array,
+always return the current mbrs_by_ref array.
+
+=head2 B<remarks( [$remark] )>
+
+Accessor to the remarks attribute.
+Accepts an optional remark to be added to the remarks array,
+always return the current remarks array.
+
+=head2 B<org( [$org] )>
+
+Accessor to the org attribute.
+Accepts an optional org, always return the current org.
+
+Points to an existing organisation object representing the entity that
+holds the resource.
+
+The 'ORG-' string followed by 2 to 4 characters, followed by up to 5 digits
+followed by a source specification.  The first digit must not be "0".
+Source specification starts with "-" followed by source name up to
+9-character length.
+
+=head2 B<tech_c( [$contact] )>
+
+Accessor to the tech_c attribute.
+Accepts an optional contact to be added to the tech_c array,
+always return the current tech_c array.
+
+=head2 B<admin_c( [$contact] )>
+
+Accessor to the admin_c attribute.
+Accepts an optional contact to be added to the admin_c array,
+always return the current admin_c array.
+
+=head2 B<notify( [$notify] )>
+
+Accessor to the notify attribute.
+Accepts an optional notify value to be added to the notify array,
+always return the current notify array.
+
+=head2 B<mnt_by( [$mnt_by])>
+
+Accessor to the mnt_by attribute.
+Accepts an optional mnt_by value to be added to the mnt_by array,
+always return the current mnt_by array.
+
+=head2 B<changed( [$changed] )>
+
+Accessor to the changed attribute.
+Accepts an optional changed value to be added to the changed array,
+always return the current changed array.
+
+=head2 B<source( [$source] )>
+
+Accessor to the source attribute.
+Accepts an optional source, always return the current source.
+
+=head2 B<mp_members( [$mp_member] )>
+
+Accessor to the mp_members attribute.
+Accepts an optional mp_member to be added to the mp_members array,
+always return the current mp_members array.
+
+This attribute performs the same function as the members attribute above.
+The difference is that mp-members allows both IPv4 and IPv6 address families
+to be specified.
+
+Explicitly lists IPv4 or IPv6 'members' of the rtr-set can be:
+
+    * inet-rtr objects
+    * other rtr-set objects
+    * ipv4 address
+    * ipv6 address
+
+=cut
+
+1;
@@ -5,7 +5,7 @@ use base qw/Net::Whois::Object/;
 # http://www.ripe.net/data-tools/support/documentation/update-ref-manual#section-27
 # http://www.apnic.net/apnic-info/whois_search/using-whois/guide/rtr-set
 #
-# From : whois -t route-set
+# From: whois -t route-set
 # % This is the RIPE Database query service.
 # % The objects are in RPSL format.
 # %
@@ -3,9 +3,9 @@ use strict;
 use warnings;
 
 use Carp;
-use Net::Whois::RIPE;
 use IPC::Open2 qw/open2/;
 use List::Util qw/max/;
+use Data::Dumper;
 
 our $LWP;
 
@@ -71,7 +71,7 @@ are strings and no more Net::Whois::Objects.
     # Add a phone number
     $person->phone(' +33 4 88 00 65 15');
 
-Some attributes can have multiple value (remarks, mnt-by...) first implementation allowed only to
+Some attributes can have multiple values (remarks, mnt-by...) first implementation allowed only to
 add one value
 
     # Add one maintener
@@ -89,7 +89,14 @@ Which is a verbose way to do exactly as the default mode above, but also
 Or even
 
     # Replace CPNY-MNT2 by REPL-MNT
-    $person->mnt_by({mode => 'replace', value => {old => 'CPNY-MNT2', old => 'REPL-MNT'}});
+    $person->mnt_by({mode => 'replace', value => {old => 'CPNY-MNT2', new => 'REPL-MNT'}});
+
+From release 2.002 you can also use the 'delete' mode to remove a specific attribute value
+
+    $person->mnt_by({mode => 'delete', value => {old => 'REPL-MNT'}});
+    
+    # Or if you want to remove all remarks (the regex '.' meaning any char, will match all remarks values)
+    $person->remarks({mode => 'delete', value => {old => '.'}});
 
 
 =head2 Dump the current state of the data
@@ -107,7 +114,8 @@ dump() handle the 'align' parameter passed though a hash ref.
 =head2 Update the RIPE database
 
 The RIPE database update is currently under heavy development.
-*The update code is to be considered as experimental.*
+
+B<*The update code is still to be considered as experimental.*>
 
 We plan to offer several ways to update the RIPE database
 
@@ -146,7 +154,7 @@ array reference of additional options to pass to the signing binary.
 
 The primary key of the object created is returned.
 The attribute used as primary key can be obtained through 
-$object->attribute('primary') 
+C<$object->attribute('primary')>
 
 =head4 Update
 
@@ -244,7 +252,7 @@ sub new {
             $block = 'comment' unless $block;
 
             # Comment line
-            $attribute = "comment";
+            $attribute = 'comment';
             $value     = $1;
 
         } elsif ( $line =~ /^[^%]\s*(.+)/ ) {
@@ -255,10 +263,13 @@ sub new {
         } elsif ( $line =~ /^$/ ) {
 
             # Blank line
-            push @results, $object;
-            $attribute = undef;
-            $block     = undef;
-            $object    = undef;
+            if ($object) {
+                $object = _object_factory( $object->{block}, $object->{value}, $object );
+                push @results, $object;
+                $attribute = undef;
+                $block     = undef;
+                $object    = undef;
+            }
             next;
 
         }
@@ -270,14 +281,28 @@ sub new {
         $block = $attribute unless $block;
 
         if ( !$object ) {
-            $object = _object_factory( $block, $value ) unless $object;
-        } elsif ($attribute) {
-            $object->$attribute($value);
+            $object = { block => $block, value => $value, attributes => [] };
+
+            # $object = _object_factory( $block, $value ) unless $object;
+            # } elsif ( $object->can($attribute) ) {
+            # $object->$attribute($value);
+            if ( $block eq 'comment' ) {
+
+                # push @{$object->{attributes}},[ 'comment', $value ];
+                next;
+            }
         }
 
+        # } else {
+        push @{ $object->{attributes} }, [ $attribute, $value ];
+
+        # } else {
+        # warn "Objects of type " . ref($object) . " do not support attribute '$attribute', but it was supplied with value '$value'\n";
+        # }
+
     }
 
-    # TODO : fix the trailing undef
+    # TODO: fix the trailing undef
     return grep {defined} @results;
 }
 
@@ -326,7 +351,7 @@ sub clone {
 =head2 B<attributes( [$type [, \@attributes]] )>
 
 Accessor to the attributes of the object. 
-$type can be 
+C<$type> can be 
 
     'primary'   Primary/Lookup key
     'mandatory' Required for update creation
@@ -336,7 +361,7 @@ $type can be
     'all'       You can't specify attributes for this special type
                 which provides all the attributes which have a type
 
-If no $type is specified, 'all' is assumed.
+If no C<$type> is specified, 'all' is assumed.
 Returns a list of attributes of the required type.
 
 =cut
@@ -383,7 +408,7 @@ sub class {
 
 =head2 B<attribute_is ( $attribute, $type )>
 
-This method return true if $attribute is of type $type.
+This method return true if C<$attribute> is of type C<$type>
 
 =cut
 
@@ -426,7 +451,7 @@ sub displayed_attributes {
 Simple naive way to display a text form of the class.
 Try to be as close as possible as the submited text.
 
-Currently the only option available is 'align' which accept a $column number as
+Currently the only option available is 'align' which accept a C<$column> number as
 parameter so that all C<< $self->dump >> produces values that are aligned
 vertically on column C<$column>.
 
@@ -556,17 +581,34 @@ sub syncupdates_create {
         }
     }
 
-    my ($key) = $self->attributes('primary');
-
     my $res = $self->_syncupdates_submit( $self->dump($dump_options), $options );
 
     if (    $res =~ /^Number of objects processed with errors:\s+(\d+)/m
          && $1 == 0
-         && $res =~ /\*\*\*Info:\s+Authorisation for\s+\[[^\]]+]\s+(.+)\s*$/m )
+         && (    $res =~ /\*\*\*Info:\s+Authorisation for\s+\[[^\]]+]\s+(.+)\s*$/m
+              || $res =~ /(?:Create SUCCEEDED|No operation): \[[^\]]+\]\s+(\S+)/m )
+        )
     {
         my $value = $1;
-        $self->_single_attribute_setget( $key, $value );
-        return $value;
+        my ($key) = $self->attributes('primary');
+
+        # some primary keys can contain spaces, in which case $value
+        # is not correct. So only use it for objects where the primary
+        # key can be generated by the RIPE DB, and where it never contains
+        # spaces. According to
+        # http://www.ripe.net/ripe/mail/archives/db-help/2013-January/000411.html
+        # this is the case for person, organization, role and key-cert
+        my %obj_types_with_autogen_key = ( KeyCert      => 1,
+                                           Organisation => 1,
+                                           Person       => 1,
+                                           Role         => 1,
+        );
+        if ( $self->class && $obj_types_with_autogen_key{ $self->class } ) {
+            $self->_single_attribute_setget( $key, $value );
+            return $value;
+        } else {
+            return $self->$key();
+        }
     } else {
         croak "Error while creating object through syncupdates API: $res";
     }
@@ -582,10 +624,10 @@ Query the RIPE database and return Net::Whois::Objects
 
 This method accepts 2 optional parameters
 
-'type' which is a regex used to filter the query result :
+'type' which is a regex used to filter the query result:
 Only the object whose type matches the 'type' parameter are returned
 
-'attribute' which is a regex used to filter the query result :
+'attribute' which is a regex used to filter the query result:
 Only the value of the attributes matching the 'attribute' parameter are
 returned
 
@@ -594,43 +636,43 @@ Net::Whois::Objects
 
 =cut
 
-sub query {
-    my ( $class, $query, $options ) = @_;
-
-    my $attribute;
-    my $type;
-
-    for my $opt ( keys %$options ) {
-        if ( $opt =~ /^attribute$/i ) {
-            $attribute = $options->{$opt};
-        } elsif ( $opt =~ /^type$/i ) {
-            $type = $options->{$opt};
-        }
-    }
-
-    my $whois    = Net::Whois::RIPE->new(%$options);
-    my $iterator = $whois->query($query);
-
-    my @objects = Net::Whois::Object->new($iterator);
-
-    if ($type) {
-        @objects = grep { ref($_) =~ /$type/i } @objects;
-    }
-
-    if ($attribute) {
-        return grep {defined} map {
-            my $r;
-            eval { $r = $_->$attribute };
-            $@ ? undef : ref($r) eq 'ARRAY' ? @$r : $r
-        } @objects;
-    } else {
-        return grep {defined} @objects;
-    }
-}
+# sub query {
+#     my ( $class, $query, $options ) = @_;
+#
+#     my $attribute;
+#     my $type;
+#
+#     for my $opt ( keys %$options ) {
+#         if ( $opt =~ /^attribute$/i ) {
+#             $attribute = $options->{$opt};
+#         } elsif ( $opt =~ /^type$/i ) {
+#             $type = $options->{$opt};
+#         }
+#     }
+#
+#     my $whois    = Net::Whois::Generic->new(%$options);
+#     my $iterator = $whois->query($query);
+#
+#     my @objects = Net::Whois::Object->new($iterator);
+#
+#     if ($type) {
+#         @objects = grep { ref($_) =~ /$type/i } @objects;
+#     }
+#
+#     if ($attribute) {
+#         return grep {defined} map {
+#             my $r;
+#             eval { $r = $_->$attribute };
+#             $@ ? undef : ref($r) eq 'ARRAY' ? @$r : $r
+#         } @objects;
+#     } else {
+#         return grep {defined} @objects;
+#     }
+# }
 
 =begin UNDOCUMENTED
 
-=head2 B<_object_factory( $type => $value )>
+=head2 B<_object_factory( $type => $value, $attributes_hashref )>
 
 Private method. Shouldn't be used from other modules.
 
@@ -640,8 +682,12 @@ the type passed as parameter.
 =cut
 
 sub _object_factory {
-    my $type  = shift;
-    my $value = shift;
+    my $type   = shift;
+    my $value  = shift;
+    my $object = shift;
+    my $rir;
+
+    my $object_returned;
 
     my %class = ( as_block     => 'AsBlock',
                   as_set       => 'AsSet',
@@ -657,7 +703,6 @@ sub _object_factory {
                   limerick     => 'Limerick',
                   mntner       => 'Mntner',
                   organisation => 'Organisation',
-                  organisation => 'Organisation',
                   peering_set  => 'PeeringSet',
                   person       => 'Person',
                   poem         => 'Poem',
@@ -670,24 +715,42 @@ sub _object_factory {
                   rtr_set      => 'RtrSet',
     );
 
-    die "Unrecognized Object (first attribute: $type = $value)" unless $class{$type};
+    die "Unrecognized Object (first attribute: $type = $value)\n" . Dumper($object) unless defined $type and $class{$type};
 
     my $class = "Net::Whois::Object::" . $class{$type};
 
+    for my $a ( @{ $object->{attributes} } ) {
+        if ( $a->[0] =~ /source/ ) {
+            $rir = $a->[1];
+            $rir =~ s/^(\S+)\s*#.*/$1/;
+            $rir = uc $rir;
+            $rir = undef if $rir =~ /^(RIPE|TEST)$/;    # For historical/compatibility reason RIPE objects aren't derived
+        }
+    }
+
+    $class .= "::$rir" if $rir;
+
     eval "require $class" or die "Can't require $class ($!)";
 
     # my $object = $class->new( $type => $value );
-    my $object = $class->new( class => $class{$type} );
+    $object_returned = $class->new( class => $class{$type} );
 
     # First attribute is always single valued, except for comments
     if ( $type eq 'comment' ) {
-        $object->_multiple_attribute_setget( $type => $value );
+        $object_returned->_multiple_attribute_setget( $type => $value );
     } else {
-        $object->_single_attribute_setget( $type => $value );
+        $object_returned->_single_attribute_setget( $type => $value );
+    }
+
+    if ( $object->{attributes} ) {
+        for my $a ( @{ $object->{attributes} } ) {
+            my $method = $a->[0];
+            $object_returned->$method( $a->[1] );
+        }
     }
 
     # return $class->new( $type => $value );
-    return $object;
+    return $object_returned;
 
 }
 
@@ -699,13 +762,38 @@ Generic setter/getter for singlevalue attribute.
 
 sub _single_attribute_setget {
     my ( $self, $attribute, $value ) = @_;
+    my $mode = 'replace';
+
+    if ( ref $value eq 'HASH' ) {
+        my %options = %$value;
+
+        if ( $options{mode} ) {
+            $mode = $options{mode};
+        }
+
+        if ( $options{value} ) {
+            $value = $options{value};
+        } else {
+            croak "Unable to determine attribute $attribute value";
+        }
+
+    }
 
     if ( defined $value ) {
 
-        # Store attribute order for dump, unless this attribute as already been set
-        push @{ $self->{order} }, $attribute unless $self->{$attribute} or $attribute eq 'class';
+        if ( $mode eq 'replace' ) {
+
+            # Store attribute order for dump, unless this attribute as already been set
+            push @{ $self->{order} }, $attribute unless $self->{$attribute} or $attribute eq 'class';
 
-        $self->{$attribute} = $value;
+            $self->{$attribute} = $value;
+        } elsif ( $mode eq 'delete' ) {
+            if ( ref $value ne 'HASH' or !$value->{old} ) {
+                croak " {old=>...} expected as value for $attribute update in delete mode";
+            } else {
+                $self->_delete_attribute( $attribute, $value->{old} );
+            }
+        }
     }
     return $self->{$attribute};
 }
@@ -756,6 +844,14 @@ sub _multiple_attribute_setget {
                     $_ = $value->{new} if $_ =~ /$old/;
                 }
             }
+        } elsif ( $mode eq 'delete' ) {
+            if ( ref $value ne 'HASH' or !$value->{old} ) {
+                croak " {old=>...} expected as value for $attribute update in delete mode";
+            } else {
+
+                # $self->{$attribute} = [grep {!/$old/} @{$self->{$attribute}}];
+                $self->_delete_attribute( $attribute, $value->{old} );
+            }
         } else {
             croak "Unknown mode $mode for attribute $attribute";
         }
@@ -765,6 +861,43 @@ sub _multiple_attribute_setget {
     return $self->{$attribute};
 }
 
+=head2 B<_delete_attribute( $attribute, $pattern )>
+
+Delete an attribute if its value match the pattern value 
+
+=cut
+
+sub _delete_attribute {
+    my ( $self, $attribute, $pattern ) = @_;
+
+    my @lines;
+
+    for my $a ( @{ $self->{order} } ) {
+        my $val = ref $self->{$a} ? shift @{ $self->{$a} } : $self->{$a};
+        push @lines, [ $a, $val ];
+    }
+
+    @lines = grep { $attribute ne $_->[0] or $_->[1] !~ /$pattern/ } @lines;
+    delete $self->{$attribute} if $self->attribute_is( $attribute, 'single' ) and $self->{$attribute} =~ /$pattern/;
+
+    $self->{order} = [];
+    for my $l (@lines) {
+        $self->{ $l->[0] } = [] if ref( $self->{ $l->[0] } );
+    }
+
+    for my $i ( 0 .. $#lines ) {
+        push @{ $self->{order} }, $lines[$i]->[0];
+        if ( $self->attribute_is( $lines[$i]->[0], 'multiple' ) ) {
+            push @{ $self->{ $lines[$i]->[0] } }, $lines[$i]->[1];
+        } else {
+            $self->{ $lines[$i]->[0] } = $lines[$i]->[1];
+
+        }
+
+    }
+
+}
+
 =head2 B<_init( @options )>
 
 Initialize self with C<@options>
@@ -866,6 +999,10 @@ sub _TYPE {
     $TYPES{ ref $_[0] || $_[0] } ||= {};
 }
 
+=head1 SEE ALSO
+
+Please take a look at L<Net::Whois::Generic> the more generic whois client built on top of Net::Whois::RIPE.
+
 =head1 TODO
 
 The update part (in RIPE database) still needs a lot of work.
@@ -7,19 +7,18 @@ use IO::Socket::INET;
 use IO::Select;
 use Iterator;
 
-use constant {
-    SOON                    => 30,
-    END_OF_OBJECT_MARK      => "\n\n",
-    EOL                     => "\015\012",
-    QUERY_KEEPALIVE         => q{-k },
-    QUERY_NON_RECURSIVE     => q{-r },
-    QUERY_REFERRAL          => q{-R },
-    QUERY_GROUPING          => q{-G },
-    QUERY_UNFILTERED        => q{-B },
-    QUERY_LIST_OBJECTS      => q{-qtypes },
-    QUERY_LIST_SOURCES      => q{-qsources },
-    QUERY_FETCH_TEMPLATE    => q{-t%s },
-    QUERY_LIMIT_OBJECT_TYPE => q{-T%s },
+use constant { SOON                    => 30,
+               END_OF_OBJECT_MARK      => "\n\n",
+               EOL                     => "\015\012",
+               QUERY_KEEPALIVE         => q{-k },
+               QUERY_NON_RECURSIVE     => q{-r },
+               QUERY_REFERRAL          => q{-R },
+               QUERY_GROUPING          => q{-G },
+               QUERY_UNFILTERED        => q{-B },
+               QUERY_LIST_OBJECTS      => q{-qtypes },
+               QUERY_LIST_SOURCES      => q{-qsources },
+               QUERY_FETCH_TEMPLATE    => q{-t%s },
+               QUERY_LIMIT_OBJECT_TYPE => q{-T%s },
 };
 
 =head1 NAME
@@ -28,11 +27,11 @@ Net::Whois::RIPE - a pure-Perl implementation of the RIPE Database client.
 
 =head1 VERSION
 
-Version 2.001000
+Version 2.005001
 
 =cut
 
-our $VERSION = 2.001000;
+our $VERSION = 2.005001;
 
 =head1 SYNOPSIS
 
@@ -56,12 +55,24 @@ If you prefer to manipulate full-fledged objects you can now use
 
   my @objects = Net::Whois::Object->query( 'AS333' );
 
+From version 2.005000 you can also use the  Net::Whois::Generic interface 
+that mimics Net::Whois::Object while offering access to data from other sources
+than RIPE (AFRINIC, APNIC)
+
+  use Net::Whois::Object;
+
+  my @objects = Net::Whois::Generic->query( 'ORG-AFNC1-AFRINIC' );
+
+Please see L<Net::Whois::Generic> documentation for more details
+
 Of course, comments are more than welcome. If you believe you can help, please
 do not hesitate in contacting me.
 
 =head1 BACKWARD COMPATIBILITY
 
-I've choose to break backwards compatibility with older versions of the L<Net::Whois::RIPE> module for several different reasons. I will try to explain and justify them here, as design documentation. I will also strive to provide practical solutions for porting problems, if any.
+I've choose to break backwards compatibility with older versions of the L<Net::Whois::RIPE> 
+module for several different reasons. I will try to explain and justify them here, as design documentation. 
+I will also strive to provide practical solutions for porting problems, if any.
 
 =head2 Architecture
 
@@ -94,7 +105,7 @@ A production release of this module will be able to feed a L<RPSL::Parser> with
 RPSL objects extracted from the RIPE Database and return full-fledged objects
 containing a parsed version of the text (way more useful than a text blob, I
 believe). 
-Net::Whois::Object (from release 2.00_010) is the first attempt toward this
+L<Net::Whois::Object> (from release 2.00_010) is the first attempt toward this
 goal.
 
   # You can now do
@@ -183,25 +194,22 @@ connection to the RIPE Database service desired.
 =cut
 
 {
-    my %default_options = (
-        hostname     => 'whois.ripe.net',
-        port         => '43',
-        timeout      => 5,
-        keepalive    => 0,
-        referral     => 0,
-        recursive    => 0,
-        grouping     => 1,
-        unfiltered   => 0,
-        types        => undef,
-        disconnected => 0,
+    my %default_options = ( hostname     => 'whois.ripe.net',
+                            port         => '43',
+                            timeout      => 5,
+                            keepalive    => 0,
+                            referral     => 0,
+                            recursive    => 0,
+                            grouping     => 1,
+                            unfiltered   => 0,
+                            types        => undef,
+                            disconnected => 0,
     );
 
     sub new {
         my ( $class, %options ) = @_;
         my %known_options;
-        $known_options{$_}
-            = exists $options{$_} ? $options{$_} : $default_options{$_}
-            foreach keys %default_options;
+        $known_options{$_} = exists $options{$_} ? $options{$_} : $default_options{$_} foreach keys %default_options;
 
         my $self = bless { __options => \%known_options }, $class;
 
@@ -340,31 +348,25 @@ Initiates a connection with the current object's configuration.
 =cut
 
 sub connect {
-    my $self       = shift;
-    my %connection = (
-        Proto      => 'tcp',
-        Type       => SOCK_STREAM,
-        PeerAddr   => $self->hostname,
-        PeerPort   => $self->port,
-        Timeout    => $self->timeout,
-        Domain     => AF_INET,
-        Multihomed => 1,
+    my $self = shift;
+    my %connection = ( Proto      => 'tcp',
+                       Type       => SOCK_STREAM,
+                       PeerAddr   => $self->hostname,
+                       PeerPort   => $self->port,
+                       Timeout    => $self->timeout,
+                       Domain     => AF_INET,
+                       Multihomed => 1,
     );
 
     # Create a new IO::Socket object
-    my $socket = $self->{__state}{socket}
-        = IO::Socket::INET->new(%connection);
-    die q{Can't connect to "}
-        . $self->hostname . ':'
-        . $self->port
-        . qq{". Reason: [$@].\n}
+    my $socket = $self->{__state}{socket} = IO::Socket::INET->new(%connection);
+    die q{Can't connect to "} . $self->hostname . ':' . $self->port . qq{". Reason: [$@].\n}
         unless defined $socket;
 
     # Register $socket with the IO::Select object
     if ( my $ios = $self->ios ) {
         $ios->add($socket) unless $ios->exists($socket);
-    }
-    else {
+    } else {
         $self->{__state}{ioselect} = IO::Select->new($socket);
     }
 
@@ -437,7 +439,8 @@ sub disconnect {
     if ( $self->is_connected ) {
         my $socket = $self->{__state}{socket};
         $socket->close;
-        $self->{__state}{ioselect}->remove($socket);
+        $self->{__state}{ioselect}->remove($socket)
+            if $self->{__state}{ioselect};
         delete $self->{__state}{socket};
     }
 }
@@ -480,7 +483,7 @@ Sends a query to the server. Returns an L<Iterator> object that will return one
 sub query {
     my ( $self, $query ) = @_;
     my $parameters = "";
-    $parameters .= q{ } . QUERY_KEEPALIVE if $self->keepalive;
+    $parameters .= q{ } . QUERY_KEEPALIVE  if $self->keepalive;
     $parameters .= q{ } . QUERY_UNFILTERED if $self->unfiltered;
     $parameters .= q{ } . QUERY_NON_RECURSIVE unless $self->recursive;
     $parameters .= q{ } . QUERY_REFERRAL if $self->referral;
@@ -527,9 +530,9 @@ connection will be terminated after this query.
 =cut
 
 sub object_types {
-    my $self = shift;
+    my $self     = shift;
     my $iterator = $self->__query(QUERY_LIST_OBJECTS);
-    while (!$iterator->is_exhausted) {
+    while ( !$iterator->is_exhausted ) {
         my $value = $iterator->value;
         return split /\s+/, $value if $value !~ /^%\s/;
     }
@@ -0,0 +1,4 @@
+use Test::More;
+eval 'use Test::CPAN::Changes';
+plan skip_all => 'Test::CPAN::Changes required for this test' if $@;
+changes_ok();
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -97,7 +96,8 @@ SKIP: {
     ok $c->is_connected, 'The client is connected.';
 
     # reconnect()
-    lives_ok { $c->reconnect } 'The client re-connected without dying.';
+    eval {$c->reconnect };
+    ok !$@,'The client re-connected without dying.';
     ok $c->is_connected, 'The client is connected (once more).';
 
     # ios()
@@ -111,17 +111,18 @@ SKIP: {
     # query()
     {
         my $iter;
-        lives_ok { $iter = $c->query('LMC-RIPE') }
-        q{Client performs queries without dying};
+        eval { $iter = $c->query('LMC-RIPE') };
+        ok !$@, q{Client performs queries without dying};
         isa_ok $iter, 'Iterator';
+        last unless $iter;
         ok $iter->isnt_exhausted, q{Iterator contains at least one result};
     }
 
     # object_types()
     {
         my @types;
-        lives_ok { @types = $c->object_types }
-        q{Client can retrieve available object types without dying.};
+        eval { @types = $c->object_types };
+        ok !$@ , q{Client can retrieve available object types without dying.};
         is $#types, 20,
           q{There are 21 known object types in the RIPE Database};
     }
@@ -129,9 +130,9 @@ SKIP: {
     # send()
 
     # disconnect()
-    lives_ok { $c->disconnect } 'The client disconnected without dying.';
+    eval { $c->disconnect };
+    ok !$@ , 'The client disconnected without dying.';
     ok !$c->is_connected, 'The client is not connected (anymore).';
 
     # DESTROY()
 }
-
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
+# use Data::Dumper;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -30,6 +30,9 @@ can_ok $o[5], qw( aut_num as_name org source ), qw( descr member_of import mp_im
     mnt_lower mnt_by mnt_routes changed);
 ok( !$o[5]->can('bogusmethod'), "No AUTOLOAD interference with ${class}::AutNum tests" );
 
+#
+# 'attributes' method
+#
 is_deeply( [ $o[0]->attributes('mandatory') ], ['comment'] );
 
 is_deeply( [ $o[0]->attributes('optional') ], [] );
@@ -39,20 +42,32 @@ is_deeply( [ $o[0]->attributes('optional') ], [ 'opt1', 'opt2', 'opt3' ] );
 is_deeply( [ $o[0]->attributes('all') ], [ 'comment', 'opt1', 'opt2', 'opt3' ] );
 is_deeply( [ $o[0]->attributes() ],      [ 'comment', 'opt1', 'opt2', 'opt3' ] );
 
-is( $o[2]->dump, "% Information related to 'AS30720 - AS30895'\n" );
+#
+# 'dump' method
+#
+is( $o[2]->dump, "\% Information related to 'AS30720 - AS30895'\n" );
 is( $o[2]->dump( { align => 8 } ), "% Information related to 'AS30720 - AS30895'\n" );
 
-my $clone = $o[3]->clone;
-isa_ok($clone, ref $o[3], "Clone object has the same type of source");
-is_deeply($clone, $o[3], "Clone object deeply similar to source");
-
-$clone = $o[3]->clone({remove => ['source','remarks','org', 'admin-c', 'tech-c', 'mnt-by','mnt-lower']});
+#
+# 'clone' method
+#
+my $full_clone = $o[3]->clone;
+isa_ok($full_clone, ref $o[3], "Clone object has the same type of source");
+is_deeply($full_clone, $o[3], "Clone object deeply similar to source");
+my $clone = $o[3]->clone({remove => ['source','remarks','org', 'admin-c', 'tech-c', 'mnt-by','mnt-lower']});
 is_deeply($clone, { class => 'AsBlock', order => ['as_block', 'descr'], as_block => 'AS30720 - AS30895', descr => ['RIPE NCC ASN block'] }, "Clone object similar with removed attribute");
 
+#
+# default 'append' mode in attribute modification
+#
 $clone->mnt_by({value =>['MNT1-ADD','MNT2-ADD']});
 is_deeply($clone->mnt_by,['MNT1-ADD','MNT2-ADD'],'Array properly added to empty multiple attribute');
 $clone->mnt_by({value =>['MNT3-ADD','MNT4-ADD']});
 is_deeply($clone->mnt_by,['MNT1-ADD','MNT2-ADD','MNT3-ADD','MNT4-ADD'],'Array properly added to multiple attribute');
+
+#
+# 'replace' mode in attribute modification
+#
 $clone->mnt_by({mode => 'replace', value => { old => 'MNT3-ADD', new => 'MNT3-RPL'}});
 is_deeply($clone->mnt_by,['MNT1-ADD','MNT2-ADD','MNT3-RPL','MNT4-ADD'],'Array properly added to multiple attribute');
 eval { $clone->mnt_by({mode => 'unknown', value => { old => 'MNT3-ADD', new => 'MNT3-RPL'}}); };
@@ -62,6 +77,23 @@ like($@ ,qr/new.*replace mode/, "new=>... expected in replace mode");
 eval { $clone->mnt_by({mode => 'replace', value => { new => 'MNT3-ADD'}}); };
 like($@ ,qr/old.*replace mode/, "old=>... expected in replace mode");
 
+#
+# 'delete' mode in attribute modification
+#
+$clone->mnt_by({mode => 'delete', value => { old => 'MNT3-RPL'}});
+is_deeply($clone->mnt_by,['MNT1-ADD','MNT2-ADD','MNT4-ADD'],'Array properly deleted in to multiple attribute');
+eval { $clone->mnt_by({mode => 'delete', value => { new => 'MNT3-ADD'}}); };
+like($@ ,qr/old.*delete mode/, "old=>... expected in delete mode");
+$clone->mnt_by({mode => 'delete', value => { old => '.'}});
+is_deeply($clone->mnt_by,[],'Array properly emptyed through delete wildcard');
+like($clone->dump,qr/as-block:\s+AS30720 - AS30895\ndescr:\s+RIPE NCC ASN block\n/,"Dump of deleted attributes ok");
+my $delete_clone = $full_clone->clone({remove=>['remarks']});
+like($full_clone->dump,qr/as-block:\s+AS30720 - AS30895\ndescr:\s+RIPE NCC ASN block\nremarks:\s+These AS Numbers are further assigned to network\nremarks:\s+operators in the RIPE NCC service region. AS\nremarks:\s+assignment policy is documented in:\nremarks:\s+<http:\/\/www.ripe.net\/ripe\/docs\/asn-assignment.html>\nremarks:\s+RIPE NCC members can request AS Numbers using the\nremarks:\s+form available in the LIR Portal or at:\nremarks:\s+<http:\/\/www.ripe.net\/ripe\/docs\/asnrequestform.html>\norg:\s+ORG-NCC1-RIPE\nadmin-c:\s+CREW-RIPE\ntech-c:\s+RD132-RIPE\nmnt-by:\s+RIPE-DBM-MNT\nmnt-lower:\s+RIPE-NCC-HM-MNT\nsource:\s+RIPE # Filtered\n/,"org full clone stil ok");
+$full_clone->mnt_lower({mode=>'delete', value => {old => 'RIPE-NCC-HM-MNT'}});
+like($full_clone->dump,qr/as-block:\s+AS30720 - AS30895\ndescr:\s+RIPE NCC ASN block\nremarks:\s+These AS Numbers are further assigned to network\nremarks:\s+operators in the RIPE NCC service region. AS\nremarks:\s+assignment policy is documented in:\nremarks:\s+<http:\/\/www.ripe.net\/ripe\/docs\/asn-assignment.html>\nremarks:\s+RIPE NCC members can request AS Numbers using the\nremarks:\s+form available in the LIR Portal or at:\nremarks:\s+<http:\/\/www.ripe.net\/ripe\/docs\/asnrequestform.html>\norg:\s+ORG-NCC1-RIPE\nadmin-c:\s+CREW-RIPE\ntech-c:\s+RD132-RIPE\nmnt-by:\s+RIPE-DBM-MNT\nsource:\s+RIPE # Filtered\n$/,"non last attribute deletion ok");
+$full_clone->source({mode=>'delete', value => {old => 'RIPE'}});
+like($full_clone->dump,qr/as-block:\s+AS30720 - AS30895\ndescr:\s+RIPE NCC ASN block\nremarks:\s+These AS Numbers are further assigned to network\nremarks:\s+operators in the RIPE NCC service region. AS\nremarks:\s+assignment policy is documented in:\nremarks:\s+<http:\/\/www.ripe.net\/ripe\/docs\/asn-assignment.html>\nremarks:\s+RIPE NCC members can request AS Numbers using the\nremarks:\s+form available in the LIR Portal or at:\nremarks:\s+<http:\/\/www.ripe.net\/ripe\/docs\/asnrequestform.html>\norg:\s+ORG-NCC1-RIPE\nadmin-c:\s+CREW-RIPE\ntech-c:\s+RD132-RIPE\nmnt-by:\s+RIPE-DBM-MNT\n$/,"last attribute deletion ok");
+
 my @objects;
 eval { @objects = Net::Whois::Object->query('AS30781', {attribute => 'remarks'}) };
 
@@ -71,18 +103,23 @@ SKIP: {
     for my $object (@objects) {
         ok(!ref($object), "query() : String returned for 'remarks' attribute filter")
     }
+}
 
-    @objects = Net::Whois::Object->query('AS30781');
+eval {    @objects = Net::Whois::Object->query('AS30781') };
+SKIP: {
+    skip "Network issue",14 if ( $@ =~ /IO::Socket::INET/ );
     for my $object (@objects) {
-        ok(ref($object) =~ /Net::Whois::Object/ , "query() : Object returned for 'remarks' attribute filter")
+        ok(ref($object) =~ /Net::Whois::Object/ , "query() : Object ".ref($object)." returned for 'remarks' attribute filter")
     }
 
-    @objects = Net::Whois::Object->query('AS30781', {type => 'asblock', attribute => 'admin_c'});
+}
+eval {    @objects = Net::Whois::Object->query('AS30781', {type => 'asblock', attribute => 'admin_c' })} ;
+SKIP: {
+    skip "Network issue",14 if ( $@ =~ /IO::Socket::INET/ );
     for my $object (@objects) {
         ok($object eq 'CREW-RIPE' , "query() : 'CREW-RIPE' returned for AsBlock and admin-c filter")
     }
 }
-
 __DATA__
 % This is the RIPE Database query service.
 % The objects are in RPSL format.
@@ -0,0 +1,89 @@
+use strict;
+use warnings;
+use Test::More qw( no_plan );
+use Data::Dumper;
+
+# synchronizes the {error,standard} output of this test.
+use IO::Handle;
+STDOUT->autoflush(1);
+STDERR->autoflush(1);
+
+our $class;
+BEGIN { $class = 'Net::Whois::Generic'; use_ok $class; }
+
+can_ok $class,
+
+  # Read-Only Accessors
+  qw( ios socket ),
+
+  # Read-Write Accessors
+  qw( hostname port timeout referral recursive grouping ),
+
+  # Connection Methods
+  qw( connect disconnect reconnect is_connected ),
+
+  # Query Methods
+  qw( query object_types send ),
+
+  # OO Support
+  qw( DESTROY );
+
+{
+    my $c = Net::Whois::Generic->new( disconnected => 1, unfiltered => 1 );
+    isa_ok $c, $class;
+
+}
+
+    my $c = $class->new( disconnected => 1 );
+
+    # connect()
+    # TODO: implement a test that doesn't requires internet connection
+    eval { $c->connect };
+
+SKIP: {
+    skip "Network issue",14 if ( $@ =~ /IO::Socket::INET/ );
+
+    ok (!$@, "The client connected without dying. $@");
+
+    # is_connected()
+    ok $c->is_connected, 'The client is connected.';
+
+    # reconnect()
+    eval {$c->reconnect };
+    ok !$@,'The client re-connected without dying.';
+    ok $c->is_connected, 'The client is connected (once more).';
+
+    # ios()
+    isa_ok $c->ios, 'IO::Select';
+    ok $c->ios->count >= 1,
+      q{There's at least one handle registered with the IO::Select object.};
+
+    # socket()
+    isa_ok $c->socket, 'IO::Socket';
+
+    # query() RIPE
+    {
+        my $as_set;
+        eval { ($as_set) = $c->query('AS-JAGUAR', {type => 'AsSet'}) };
+        ok !$@, q{Client performs queries without dying $@};
+        isa_ok $as_set, 'Net::Whois::Object::AsSet';
+    }
+
+    # object_types()
+    {
+        my @types;
+        eval { @types = $c->object_types };
+        ok !$@ , q{Client can retrieve available object types without dying.};
+        is $#types, 20,
+          q{There are 21 known object types in the RIPE Database};
+    }
+
+    # send()
+
+    # disconnect()
+    eval { $c->disconnect };
+    ok !$@ , 'The client disconnected without dying.';
+    ok !$c->is_connected, 'The client is not connected (anymore).';
+
+    # DESTROY()
+}
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 # use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 use Net::Whois::Object;
 
 # synchronizes the {error,standard} output of this test.
@@ -66,6 +65,11 @@ is_deeply( $object->tech_c(), ['NC345-RIPE'], 'tech_c properly parsed' );
 $object->tech_c('Added tech_c');
 is( $object->tech_c()->[1], 'Added tech_c', 'tech_c properly added' );
 
+# Test 'abuse_c'
+$tested{'abuse_c'}++;
+is_deeply( $object->abuse_c(), 'NC789-RIPE', 'abuse_c properly parsed' );
+
+is( $object->tech_c()->[1], 'Added tech_c', 'tech_c properly added' );
 # Test 'mnt_by'
 $tested{'mnt_by'}++;
 is_deeply( $object->mnt_by(), [ 'RIPE-NCC-END-MNT', 'MAIN-FR-MNT' ], 'mnt_by properly parsed' );
@@ -149,6 +153,7 @@ descr:           FRANCE
 org:             ORG-MISC01-RIPE
 admin-c:         NC123-RIPE
 tech-c:          NC345-RIPE
+abuse-c:         NC789-RIPE
 mnt-by:          RIPE-NCC-END-MNT
 mnt-by:          MAIN-FR-MNT
 notify:          MAIN-FR-MNT
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -131,9 +130,9 @@ is( $object->changed()->[1], 'abc@examplenet.com 20121231', 'changed properly ad
 
 # Test 'source'
 $tested{'source'}++;
-is( $object->source(), 'APNIC', 'source properly parsed' );
-$object->source('RIPE');
-is( $object->source(), 'RIPE', 'source properly set' );
+is( $object->source(), 'RIPE', 'source properly parsed' );
+$object->source('APNIC');
+is( $object->source(), 'APNIC', 'source properly set' );
 
 # Test 'org'
 $tested{'org'}++;
@@ -164,5 +163,5 @@ mnt-routes:  MAINT-EXAMPLENET-AP
 mnt-domains: MAINT-EXAMPLENET-AP
 mnt-irt:     IRT-EXAMPLENET-AP
 changed:     abc@examplenet.com 20101231
-source:      APNIC
+source:      RIPE
 
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -20,7 +19,7 @@ isa_ok $object, $class;
 
 # Non-inherited methods
 can_ok $object, qw( organisation org_name org_type descr remarks address phone
-    e_mail fax_no org admin_c tech_c ref_nfy mnt_ref notify mnt_by changed source);
+    e_mail fax_no org abuse_c admin_c tech_c ref_nfy mnt_ref notify mnt_by changed source);
 
 # Check if typed attributes are correct
 can_ok $object, $object->attributes('mandatory');
@@ -86,6 +85,12 @@ is_deeply( $object->language(), ['FR','EN'], 'language properly parsed' );
 $object->language('ES');
 is( $object->language()->[2], 'ES', 'language properly added' );
 
+# Test 'abuse_c'
+$tested{'abuse_c'}++;
+is( $object->abuse_c(), 'abuse@somewhere.com', 'abuse_c properly parsed' );
+$object->abuse_c('abuse3@somewhere.com');
+is( $object->abuse_c(), 'abuse3@somewhere.com', 'abuse_c properly changed' );
+
 # Test 'admin_c'
 $tested{'admin_c'}++;
 is_deeply( $object->admin_c(), ['CPNY-ADM'], 'admin_c properly parsed' );
@@ -170,6 +175,7 @@ phone:          +33 1 75 75 75 01
 fax-no:         +33 1 75 75 75 91
 e-mail:         someone@somewhere.com
 geoloc:         OTHER
+abuse-c:        abuse@somewhere.com
 language:       FR
 language:       EN
 admin-c:        CPNY-ADM
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -129,9 +128,9 @@ is( $object->changed()->[1], 'someone@demo.com 20120228', 'changed properly adde
 
 # Test 'source'
 $tested{'source'}++;
-is( $object->source(), 'APNIC', 'source properly parsed' );
-$object->source('RIPE');
-is( $object->source(), 'RIPE', 'source properly set' );
+is( $object->source(), 'RIPE', 'source properly parsed' );
+$object->source('APNIC');
+is( $object->source(), 'APNIC', 'source properly set' );
 
 # Common tests
 do 't/common.pl';
@@ -160,6 +159,6 @@ remarks:        24/24 7/7
 remarks:        https://www.demo.com
 changed:        someone@demo.com 20120131
 notify:         someone@demo.com
-source:         APNIC
+source:         RIPE
 
 
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More qw( no_plan );
-use Test::Exception;
 
 # synchronizes the {error,standard} output of this test.
 use IO::Handle;
@@ -1,7 +1,6 @@
 use strict;
 use warnings;
 use Test::More;
-use Test::Exception;
 use Net::Whois::RIPE;
 use Net::Whois::Object;
 
@@ -23,7 +22,7 @@ unless ($LWP) {
     plan skip_all => 'LWP::UserAgent installation required for update';
 }
 
-plan tests => 5;
+plan tests => 6;
 
 my $MNTNER = $ENV{TEST_MNTNER};
 my $PASSWD = $ENV{TEST_MNTNER_PASSWORD};
@@ -39,9 +38,10 @@ my $email_before = $person->e_mail()->[0];
 
 my $person_id = $person->syncupdates_create( { password => $PASSWD, align => 8 } );
 ok($person_id);
+ok($person_id ne 'AUTO-1', 'person ID has been generated by RIPE db');
 
 my $whois = Net::Whois::RIPE->new( hostname => 'whois-test.ripe.net' );
-my $iterator = $whois->query($person_id);
+my $iterator = $whois->query(" -B $person_id");
 
 ($person) = grep { ( $_->class() eq 'Person' ) and ( $_->nic_hdl eq $person_id ) } Net::Whois::Object->new($iterator);
 
@@ -50,7 +50,7 @@ my $email_after = $person->e_mail('arhuman2@gmail.com');
 
 $person->syncupdates_update( { password => $PASSWD, align => 10 } );
 
-$iterator = $whois->query($person_id);
+$iterator = $whois->query("-B $person_id");
 ($person) = grep { ( $_->class() eq 'Person' ) and ( $_->nic_hdl eq $person_id ) } Net::Whois::Object->new($iterator);
 
 is_deeply( $person->e_mail(), $email_after, "Same as set name" );
@@ -0,0 +1,85 @@
+use strict;
+use warnings;
+use Test::More;
+use Net::Whois::RIPE;
+use Net::Whois::Object;
+
+our $LWP;
+BEGIN {
+    $LWP = do {
+        eval {
+            require LWP::UserAgent;
+        };
+        ($@) ? 0 : 1;
+    };
+}
+
+unless ( $ENV{TEST_MNTNER} && $ENV{TEST_MNTNER_PGPKEY} ) {
+    warn(<<'WARNING');
+
+Set TEST_MNTNER, TEST_MNTNER_PGPKEY environment vars for live testing
+    TEST_MNTNER being a maintener's nic-hdl in the RIPE test database
+    TEST_MNTNER_PGPKEY being the key ID of an key-cert associated with
+    the maintainer object
+WARNING
+    plan skip_all => ' Set environment vars for server testing';
+}
+
+unless ($LWP) {
+    plan skip_all => 'LWP::UserAgent installation required for update';
+}
+
+plan tests => 5;
+
+my $MNTNER = $ENV{TEST_MNTNER};
+my $PGPKEY = $ENV{TEST_MNTNER_PGPKEY};
+
+my @lines = <DATA>;
+map {s/MNTNER/$MNTNER/} @lines;
+
+my @o      = Net::Whois::Object->new(@lines);
+my $person = shift @o;
+my $mntner = shift @o;
+
+my $email_before = $person->e_mail()->[0];
+
+my $person_id = $person->syncupdates_create( { pgpkey => $PGPKEY } );
+ok($person_id);
+
+my $whois = Net::Whois::RIPE->new( hostname => 'whois-test.ripe.net' );
+my $iterator = $whois->query($person_id);
+
+($person) = grep { ( $_->class() eq 'Person' ) and ( $_->nic_hdl eq $person_id ) } Net::Whois::Object->new($iterator);
+
+is_deeply( $person->e_mail(), [$email_before], "Same name from previous" );
+my $email_after = $person->e_mail('arhuman2@gmail.com');
+
+$person->syncupdates_update( { pgpkey => $PGPKEY } );
+
+$iterator = $whois->query($person_id);
+($person) = grep { ( $_->class() eq 'Person' ) and ( $_->nic_hdl eq $person_id ) } Net::Whois::Object->new($iterator);
+
+is_deeply( $person->e_mail(), $email_after, "Same as set name" );
+
+isa_ok( $person, 'Net::Whois::Object::Person', 'Found a Person' );
+
+$person->syncupdates_delete( { pgpkey => $PGPKEY } );
+
+$whois = Net::Whois::RIPE->new( hostname => 'whois-test.ripe.net' );
+$iterator = $whois->query($person_id);
+
+($person) = grep { $_->class() eq 'Response' } Net::Whois::Object->new($iterator);
+
+like( $person->response, qr/ERROR:101:/, 'Deleted Person not found' );
+
+__DATA__
+person: Joh Doe
+address: 1 Avenue de la Gare
+address: 75001 Paris
+phone: +33 1 01 01 01 01
+e-mail: arhuman@gmail.com
+nic-hdl: AUTO-1
+mnt-by: MNTNER
+changed: arhuman@gmail.com 
+source: TEST
+
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+
+use Test::More qw(no_plan);
+
+use_ok 'Net::Whois::Generic';
+
+my $c = Net::Whois::Generic->new( disconnected => 1, unfiltered => 1 );
+isa_ok $c, 'Net::Whois::Generic';
+
+my $org;
+eval { ($org) = $c->query( 'ORG-AFNC1-AFRINIC', { type => 'organisation' } ) };
+ok !$@, qq{Client performs queries without dying $@};
+isa_ok $org, 'Net::Whois::Object::Organisation::AFRINIC';
+
+my $inetnum;
+my @o;
+eval { @o = $c->query('105.0.0.1') };
+ok !$@, qq{Client performs queries without dying $@};
+for my $o (@o) {
+    my $type = ref $o;
+    ok( $type =~ /(AFRINIC|Information)/, "Object " . $o->class . " returned" );
+}
+
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+
+use Test::More qw(no_plan);
+
+use_ok 'Net::Whois::Generic';
+
+my $c = Net::Whois::Generic->new( disconnected => 1, unfiltered => 0 );
+isa_ok $c, 'Net::Whois::Generic';
+
+my $mntner;
+eval { ($mntner) = $c->query( 'MAINT-APNIC-AP', { type => 'mntner' } ) };
+ok !$@, qq{Client performs queries without dying $@};
+isa_ok $mntner, 'Net::Whois::Object::Mntner::APNIC';
+
+my $inetnum;
+my @o;
+eval { @o = $c->query('101.0.0.0/8') };
+ok !$@, qq{Client performs queries without dying $@};
+for my $o (@o) {
+    my $type = ref $o;
+    ok( $type =~ /(APNIC|Information)/, "Object " . $o->class . " returned" );
+}
@@ -35,9 +35,6 @@ for my $a ( $object->attributes('multiple') ) {
 # Check that all attributes have been tested
 
 for my $a ( $object->attributes('all') ) {
-    # Check that each attribute has been tested
-    ok ($tested{ $a }, "Attribute $a has been tested");
-
     # Check that each attribute is set either to 'single' or 'multiple'
     ok ($object->attribute_is($a, 'single') or $object->attribute_is($a, 'multiple'), "$a is either single or multiple");
     ok ($object->attribute_is($a, 'single') != $object->attribute_is($a, 'multiple'), "$a can't be both single".$object->attribute_is($a,'single')." and multi".$object->attribute_is($a,'multiple'));