Net-IP-Identifier
view release on metacpan or search on metacpan
lib/Net/IP/Identifier/WhoisParser.pm view on Meta::CPAN
# PODNAME: Net::IP::Identifier::WhoisParser
# ABSTRACT: parse WHOIS result, extracting particular information
#
# AUTHOR: Reid Augustin (REID)
# EMAIL: reid@hellosix.com
# CREATED: Sat May 2 15:51:45 PDT 2015
#===============================================================================
use 5.002;
use strict;
use warnings;
package Net::IP::Identifier::WhoisParser;
use Math::BigInt;
use Net::IP; # for IP_IDENTICAL, OVERLAP, etc
use Net::IP::Identifier::Net;
use Net::IP::Identifier::Regex;
use Moo;
use namespace::clean;
our $VERSION = '0.111'; # VERSION
has verbose => ( # verbose mode
is => 'rw',
);
has text => (
is => 'rw',
);
has relevant_lines => (
is => 'lazy',
default => \&get_relevant_lines,
);
has entity => ( # if entity is found in the WHOIS result from entity strings
is => 'lazy',
default => \&get_entity,
);
has range => ( # a Net::IP::Identifier::Net object
is => 'lazy',
default => \&get_range,
);
has _entity => ( # if entity is found before ->entity call, stash it here
is => 'rw',
);
has _range => ( # if range is found before ->range call, stash it here
is => 'rw',
);
# some class variables
#my $Re = Net::IP::Identifier::Regex->new;
#my $re_any = $Re->IP_any;
#my $re_netblock = $Re->netblock;
my @whois_stop_regexs = ( # lines beyond which we should not go
qr[^parent:]i,
qr[^route([s6])?:]i,
qr[^mnt-routes:]i,
);
my @whois_range_regexs = ( # lines which might contain the range
qr[^inet6?num:\s*(.+)]i,
qr[^NetRange:\s*(.+)]i,
qr[^CIDR:\s*(\S+)]i,
qr[^Network:IP-Network(?:-Block)?:\s*(.+)]i,
qr/^a\.\s*\[Network Number\]\s*(.*)/i,
);
my @whois_entity_regexs = ( # lines that might contain the entity
qr[^Organization:\s*(.*)]i,
qr[^org-name:\s*(.*)]i,
qr[^descr:\s*(.*)]i,
qr[^owner:\s*(.*)]i,
qr[^Network:Org-Name:(.*)]i,
qr/^g\.\s*\[Organization\]\s*(.*)/i,
);
sub get_relevant_lines {
my ($self) = @_;
my @lines;
my $non_server_lines = 0;
for my $line (split "\n", $self->text) {
$line =~ s/\s*$//;
next if (not $line =~ m/\S/); # skip blank lines
if ($line =~ m/^[#%]/) { # comments
if ($line =~ m/ Information related to / and
$non_server_lines > 0) { # if it's not the first thing
last; # skip everything else
}
next; # skip comments
}
if ($line =~ m/^No match for "/ or
$line =~ m/^descr:.* address block not managed by/) {
return []; # no relevant lines
}
for my $re (@whois_stop_regexs) {
last if ($line =~ m/$re/);
}
push @lines, $line;
$non_server_lines++ if (not $line =~ m/^\[/);
# check for ARIN style listing:
if (my ($entity, $range) = $line =~ m/(.*?) \S+ \(NET6?[\da-fA-F-]+\) (.*)/) {
$range = Net::IP::Identifier::Net->new($range);
if (defined $self->_range and
$self->_range->overlaps($range) == $IP_A_IN_B_OVERLAP) {
# previous _range is inside new range. we want
# the smallest, so swap
$range = $self->_range;
$entity = $self->_entity;
}
else {
}
$self->_range($range);
$self->_entity($entity);
}
}
return \@lines;
}
sub get_range {
( run in 0.754 second using v1.01-cache-2.11-cpan-df04353d9ac )