File Coverage

blib/lib/XML/NmapParser.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package NmapParser;
2              
3 1     1   156862 use strict;
  1         2  
  1         31  
4 1     1   5 use warnings;
  1         2  
  1         34  
5              
6 1     1   457 use XML::NmapParser::Host;
  0            
  0            
7             use XML::NmapParser::Host::Service;
8             use XML::NmapParser::Host::OS;
9             use XML::NmapParser::Host::Script;
10             use XML::NmapParser::Host::TraceHop;
11              
12             use Exporter qw(import);
13              
14             our $VERSION = "0.1";
15             our @EXPORT_OK = qw(new parse livehosts RecursiveXMLtags);
16              
17              
18             sub new {
19             my $pkg = shift;
20             my $self = bless {}, $pkg;
21             $self->initialize(@_);
22             $self;
23             }
24              
25             sub initialize {
26             my $self = shift;
27             $self->{stem} = shift;
28             $self->{english} = shift;
29             }
30            
31            
32             sub parse {
33            
34             my ($self,$filename) = @_;
35            
36             $self->{parsed} = {};
37            
38             my $parser = XML::LibXML->new();
39             my $nmapXML = $parser->parse_file($filename);
40            
41             foreach ( $nmapXML->findnodes('/nmaprun') ) {
42             if ( $_->hasAttributes() ) {
43             for my $attribute ( $_->attributes() ) { $self->{parsed}{nmaprun}{$attribute->name} = $attribute->getValue;}
44             }
45             }
46             foreach ( $nmapXML->findnodes('/nmaprun/scaninfo') ) {
47             if ( $_->hasAttributes() ) {
48             for my $attribute ( $_->attributes() ) {$self->{parsed}{scaninfo}{$attribute->name} = $attribute->getValue;}
49             }
50             }
51            
52             foreach ( $nmapXML->findnodes('/nmaprun/runstats')) {
53             if ( $_->hasAttributes() ) {
54             for my $attribute ( $_->attributes() ) { $self->{parsed}{runstats}{$attribute->name} = $attribute->getValue; }
55             }
56             if ( $_->nonBlankChildNodes() ) {
57             for my $child ( $_->nonBlankChildNodes() ) {
58             my $name = $child->nodeName;
59             if ( $child->hasAttributes() ) {
60             for my $attribute ( $child->attributes() ) { $self->{parsed}{runstats}{$name}{$attribute->name} = $attribute->getValue;}
61             }
62             }
63             }
64             }
65            
66             # need to add logic to get Verbose and debugging data.....
67             #
68            
69             #----------------------------------------------------------------------------------------------------------------------------------------
70             # room for cleaner code below.....
71             my @Hosts;
72            
73             for my $HOST ( $nmapXML->findnodes('/nmaprun/host') ) {
74             my %host;
75             if ( $HOST->hasAttributes() ) {
76             for my $attribute ( $HOST->attributes() ) { $host{$attribute->name} = $attribute->getValue; }
77             }
78             foreach ($HOST->nonBlankChildNodes()) {
79             my $name = $_->nodeName;
80            
81             if ( $_->hasAttributes() ) {
82             if ( defined($host{$name})) {
83             my %hash;
84             my @current;
85             push(@current, {%{$host{$name}}});
86            
87             for my $attribute ( $_->attributes() ) {
88             $hash{$attribute->name} = $attribute->getValue;
89             }
90             push(@current, {%hash});
91             $host{$name} = [@current];
92             } else {
93             for my $attribute ( $_->attributes() ) {
94             $host{$name}{$attribute->name} = $attribute->getValue;
95             }
96             }
97             }
98             if ( $name eq "ports") {
99             my @ports;
100             if ( $_->hasChildNodes() ) {
101             for my $node ($_->nonBlankChildNodes()) {
102             my %port;
103             my %extraports;
104             my @cpe;
105            
106             if ( $node->nodeName() eq "extraports") {
107             if ( $node->hasAttributes() ) {
108             for my $attribute ( $node->attributes() ) {$extraports{$attribute->name} = $attribute->getValue;}
109             }
110             if ($node->hasChildNodes()) {
111             for my $n2 ($node->nonBlankChildNodes()) {
112             for my $attribute ( $n2->attributes() ) {$extraports{reasons}{$attribute->name} = $attribute->getValue;}
113             }
114             }
115             push(@{$host{extraports}}, { %extraports } );
116             next;
117             }
118             elsif ( $node->nodeName() eq "port") {
119             my @scripts;
120             if ( $node->hasAttributes() ) {for my $attribute ( $node->attributes() ) {$port{$attribute->name} = $attribute->getValue;} }
121             if ($node->hasChildNodes()) {
122             for my $n2 ($node->nonBlankChildNodes()) {
123             my $child = $n2->nodeName();
124             if ($child eq "script") {
125             my %script;
126             if ( $n2->hasAttributes() ) {for my $attribute ( $n2->attributes() ) {
127             $script{$attribute->name} = $attribute->getValue;}
128             }
129             if ( $n2->hasChildNodes()) {
130             for my $n3 ( $n2->nonBlankChildNodes()) {
131             my $elemKey = 0;
132             if ( $n3->hasAttributes() ) {
133             for my $attribute ( $n3->attributes() ) {
134             $elemKey = $attribute->getValue;
135             if ( defined($elemKey)) { $script{elem}{$elemKey} = $n3->textContent; }
136             }
137             }
138             }
139             }
140             push(@scripts, {%script});
141            
142             } else {
143             if ( $n2->hasAttributes() ) {for my $attribute ( $n2->attributes() ) {$port{$child}{$attribute->name} = $attribute->getValue;}}
144             if ( $n2->hasChildNodes()) {
145             for my $n3 ( $n2->nonBlankChildNodes()) {
146             if ( $n3->nodeName() eq "cpe" ) {
147             if ( $n3->hasAttributes() ) {
148             for my $attribute ( $n3->attributes() ) {
149             $attribute->name = $attribute->getValue;
150             push (@cpe, $attribute->getValue );
151             }
152             } else { push (@cpe,$n3->textContent); }
153             } else {
154             if ( $n3->hasAttributes() ) {for my $attribute ( $n3->attributes() ) {$port{$n3->nodeName()}{$attribute->name} = $attribute->getValue;}}
155             }
156             }
157             }
158             }
159             if ( $#cpe > -1 ) { $port{service}{cpe} = [ @cpe ];}
160             if ( $#scripts > -1 ) { $port{scripts} = [ @scripts]; }
161             }
162             }
163             # print " ";
164             push(@{$host{ports}}, { %port } );
165            
166             }
167             }
168             }
169             } elsif ( $name eq "os") {
170             my %os;
171             if ( $_->hasChildNodes() ) {
172             my @portsused;
173             my @OSmatch;
174             for my $node ($_->nonBlankChildNodes()) {
175             my @cpe;
176             my $name1 = $node->nodeName();
177             if ( $name1 eq "portused") {
178             my %hash;
179             if ( $node->hasAttributes() ) {
180             for my $attribute ( $node->attributes() ) { $hash{$attribute->name} = $attribute->getValue; }
181             }
182             push(@portsused,{%hash});
183             } elsif ( $name1 eq "osmatch") {
184             my @match;
185             my %OSmatch;
186             if ( $node->hasAttributes() ) {for my $attribute ( $node->attributes() ) {$OSmatch{$attribute->name} = $attribute->getValue;} }
187             if ($node->hasChildNodes()) {
188             my @osclass;
189             for my $n2 ($node->nonBlankChildNodes()) {
190             if ( $n2->nodeName() eq "osclass" ) {
191             my @cpe;
192             my %hash;
193             if ( $n2->hasAttributes() ) {for my $attribute ( $n2->attributes() ) {$hash{$attribute->name} = $attribute->getValue;}}
194             if ( $n2->hasChildNodes()) {
195             for my $n3 ( $n2->nonBlankChildNodes()) {
196             if ( $n3->nodeName() eq "cpe" ) {
197             if ( $n3->hasAttributes() ) {
198             for my $attribute ( $n3->attributes() ) {
199             $attribute->name = $attribute->getValue;
200             push (@cpe, $attribute->getValue );
201             }
202             } else { push (@cpe,$n3->textContent); }
203             }
204             }
205             }
206             if ( $#cpe > -1 ) { $hash{cpe} = [ @cpe]; }
207             push(@osclass, { %hash } );
208             }
209             }
210             if ( $#osclass > "-1" ) { $OSmatch{osclass} = [ @osclass]; }
211             }
212             push( @OSmatch, { %OSmatch });
213             } elsif ( $name1 eq "osfingerprint") {
214             if ( $node->hasAttributes() ) {for my $attribute ( $node->attributes() ) {$os{$name1}{$attribute->name} = $attribute->getValue;} }
215             }
216              
217             }
218             if ( $#portsused > "-1") { $os{portsused} = [ @portsused ]; }
219             if ( $#OSmatch > "-1" ) { $os{osmatch} = [ @OSmatch ]; }
220            
221             $host{os} = { %os };
222            
223             }
224             } elsif ( $name eq "hostnames") {
225             my %hostname;
226             if ( $_->hasChildNodes() ) {
227             for my $node ($_->nonBlankChildNodes()) {
228             if ( $node->hasAttributes() ) {for my $attribute ( $node->attributes() ) {$hostname{$attribute->name} = $attribute->getValue;} }
229             if ($node->hasChildNodes()) {
230             for my $n2 ($node->nonBlankChildNodes()) {
231             if ( $n2->hasAttributes() ) { for my $attribute ( $n2->attributes() ) {$hostname{$attribute->name} = $attribute->getValue;} }
232             }
233             }
234             push(@{$host{hostname}},{%hostname});
235             }
236             }
237             } elsif ( $name eq "trace") {
238             if ( $_->hasAttributes() ) {
239             for my $attribute ( $_->attributes() ) {
240             $host{traceroute}{$attribute->name} = $attribute->getValue;
241             }
242             }
243             for my $T ( $_->nonBlankChildNodes() ) {
244             my %hop;
245             if ( $T->hasAttributes() ) {
246             for my $attribute ( $T->attributes() ) {
247             $hop{$attribute->name} = $attribute->getValue;
248             }
249             }
250             push(@{$host{traceroute}{hop}}, {%hop} );
251             }
252             # next;
253             } elsif ( $name eq "hostscript" ) {
254             my @hostscripts;
255             if ( $_->hasAttributes() ) {
256             for my $attribute ( $_->attributes() ) { $host{hostscript}{$attribute->name} = $attribute->getValue; }
257             }
258             if ( $_->hasChildNodes() ) {
259             for my $node ($_->nonBlankChildNodes()) {
260             my %script;
261             if ( $node->nodeName() eq "script" ) {
262             if ( $node->hasAttributes() ) {
263             for my $attribute ( $node->attributes() ) { $script{$attribute->name} = $attribute->getValue; }
264             if ( $node->hasChildNodes() ) {
265             for my $n2 ( $node->nonBlankChildNodes() ) {
266             my $elemKey;
267             for my $attribute ( $n2->attributes() ) { $elemKey = $attribute->getValue; }
268             $script{elem}{$elemKey} = $n2->textContent;
269             }
270             }
271             }
272             }
273             push(@hostscripts, {%script} );
274             }
275             }
276             $host{hostscript}{scripts} = [ @hostscripts ];
277             }
278             }
279              
280             push(@Hosts,{%host})
281             }
282             $self->{parsed}{hosts} = [ @Hosts ] ;
283             undef $nmapXML;
284             return 0;
285             }
286            
287              
288             sub nmap_version {
289             my ($self) = @_;
290             return $self->{parsed}{nmaprun}{version};
291             }
292             sub numservices {
293             my ($self) = @_;
294             return $self->{parsed}{scaninfo}{numservices};
295             }
296              
297             sub scan_args {
298             my ($self) = @_;
299             return $self->{parsed}{nmaprun}{args};
300             }
301              
302             sub scan_type_proto {
303             my ($self) = @_;
304             return $self->{parsed}{scaninfo}{protocol};
305             }
306              
307             sub scan_types {
308             my ($self) = @_;
309             return $self->{parsed}{scaninfo}{type};
310             }
311              
312              
313             sub start_str {
314             my ($self) = @_;
315             return $self->{parsed}{nmaprun}{startstr};
316             }
317              
318             sub start_time {
319             my ($self) = @_;
320             return $self->{parsed}{nmaprun}{start};
321             }
322              
323             sub finished_str {
324             my ($self) = @_;
325             return $self->{parsed}{runstats}{finished}{timestr};
326             }
327             sub finished_time {
328             my ($self) = @_;
329             return $self->{parsed}{runstats}{finished}{time};
330             }
331             sub time_str {
332             my ($self) = @_;
333             return $self->{parsed}{runstats}{finished}{timestr};
334             }
335              
336             sub xml_version {
337             my ($self) = @_;
338             return $self->{parsed}{nmaprun}{xmloutputversion};
339             }
340              
341             sub live {
342             my ($self) = @_;
343             return $self->{parsed}{runstats}{hosts}{up};
344             }
345              
346             sub down {
347             my ($self) = @_;
348             return $self->{parsed}{runstats}{hosts}{down};
349             }
350              
351              
352             sub scanned {
353             my ($self) = @_;
354             return $self->{parsed}{runstats}{hosts}{total};
355             }
356              
357             sub get_address {
358             my ($self,$state,$type) = @_;
359             my @list;
360             foreach ( @{$self->{parsed}{hosts}}) {
361             if ((defined($state)) && ($_->{status}{state} ne $state) ) {
362             next;
363             } else {
364             if ( ref($_->{address}) eq "HASH" ) {
365             if ( $_->{address}{addrtype} eq $type) {
366             push(@list, $_->{address}{addr});
367             }
368             } else {
369             for my $A ( @{$_->{address}}) {
370             if ( $A->{addrtype} eq $type ) {
371             push(@list, $A->{addr});
372             }
373             }
374             }
375             }
376             }
377             return @list;
378             }
379              
380             sub get_ips {
381             my ($self,$state,$type) = @_;
382             if ( ! defined($type)) { $type = "ipv4"; }
383             my @iplist = get_address($self,$state,$type);
384              
385             return @iplist;
386             }
387              
388             sub get_host {
389            
390             my ($self,$hostIP) = @_;
391             my $host;
392             foreach ( @{$self->{parsed}{hosts}}) {
393             if (ref($_->{address}) eq "HASH" ) {
394             $host = $_ if ( $_->{address}{addr} eq $hostIP );
395             } elsif (ref($_->{address}) eq "ARRAY") {
396             for my $element ( @{$_->{address}}) {
397             $host = $_ if ( $element->{addr} eq $hostIP );
398             }
399             }
400             }
401            
402             my $HOST = NmapParser::Host->new($host);
403             return $HOST;
404            
405             }
406              
407              
408              
409             __END__