#!/usr/local/bin/perl
#  checks a website for an xml file to verify the health of exchange
#

# nagios: -epn
# Above line tells nagios not to use ePN.
# Must be in first 10 lines of file.


use Getopt::Long qw(:config no_ignore_case);
use strict;
use warnings;
no warnings 'uninitialized';
no warnings 'redefine';
use LWP::Simple;
use LWP::Protocol::http;
use XML::LibXML;
use Data::Dumper;

use vars qw( $host $url $help $verbose 
	@crits @warns @oks $rc $sep);

########################
sub usage() {
        my($rc) = @_;
        print "Usage: $0 [options] -H <host>
        -H s  hostname
        -v    verbose
        -h    help
";
        exit $rc;

}

sub get_test_results();

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

Getopt::Long::Configure ("bundling");
GetOptions('H=s' => \$host,
	   'v' => \$verbose, 
	   'h' => \$help);

&usage( 0 ) if ( $help );
&usage( 1 ) if ( ! $host );

get_test_results();

$rc = 0;
$sep = '';
if ( $#crits >= 0 ) {
    $rc = 2;
    print "CRITICAL ", join( ", ", @crits );
    $sep = '; ';
    }
if ( $#warns >= 0 ) {
    $rc = 1 if ( $rc == 0 );
    print $sep, "Warning ", join( ", ", @warns );
    $sep = '; ';
    }
if ( $rc == 0 || $verbose ) {
    print $sep, "Ok ", join( ", ", @oks );
    $sep = '; ';
    }
print "\n";
exit $rc;


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

sub get_test_results() {

    my $url = "https://" . $host . "/exchange.xml";
    @LWP::Protocol::http::EXTRA_SOCK_OPTS = ( SSL_verify_mode => 0 );
    my $ua = LWP::UserAgent->new; 
    $ua->ssl_opts( verify_hostname => 0 );
    my $req = HTTP::Request->new( GET => $url );
    $req->protocol( 'HTTP/1.0' ); 
    my $res = $ua->request($req);
    my $data = $res->content;

    if (! defined($data) ) { 
	push @crits, "Connection failed"; 
	return; 
	}

    if ( $verbose ) { 
	print STDERR "\nraw data:\n$data\n\n";
	}

    # look for </Tests> closing tag, in unicode
    if ( $data !~ m%\000<\000/\000T\000e\000s\000t\000s\000>% ) { 
	push @crits, "exchange server returned invalid Tests XML file";
	return;
	}

    my $parser = XML::LibXML->new();
    $parser->set_option( 'recover', 1 );
    $parser->set_option( 'suppress_errors', 1 );
    $parser->set_option( 'suppress_warnings', 1 );
    my $doc    = $parser->load_xml(string => $data);

    my $nok = 0;
    foreach my $test ($doc->findnodes('/Tests/test')) {
	my $result = $test->findnodes('./result');
	my $name = $test->findnodes('./name');
	$verbose && print STDERR $name->to_literal . " ==> " . $result->to_literal, "\n";

	my $res_val = int($result->to_literal());
	if ($res_val == 1) {
		push @warns, $name->to_literal;
	    }
	elsif ($res_val == 2) {
		push @crits, $name->to_literal;
	    }
	else { 
	    $nok++;
	    }
	}

    if ( $nok < 1 ) { 
	push @crits, "exchange server did not return any test results in XML";
	}
    else { 
	push @oks, "$nok tests ok";
	}
    }

