#!/usr/bin/perl -w
use strict;
use XML::DOM;
use IO::Socket;
require "../scripts/log.pl";

my $dolog = 0;

#--- Program Agent Socket definition
#my $host=inet_aton("localhost");
my $host="localhost";
my $port="1500";
#my $paddr=sockaddr_in($port,$iaddr);

#--- End of section
print "Content-type: text/plain\n\n";

#--- Add /usr/local/bin to $ENV{'PATH'}
my $env_path=$ENV{'PATH'};
my $add_path_flag = 1;
my @pathes = split(/:/, $env_path);
my $path;

foreach $path(@pathes) {
    if ( $path eq "/usr/local/bin" ) {
	$add_path_flag = 0;
    }
}
$ENV{'PATH'} = $env_path . ":/usr/local/bin" if $add_path_flag;

#----------------------------------------
## Parse incoming data
##
my $rollback_flag = 0;
my $buffer;
my %params;

if ($ENV{REQUEST_METHOD} eq 'POST') {
    read(STDIN, $buffer, $ENV{CONTENT_LENGTH});
    $buffer .= "&";
    $buffer .= $ENV{QUERY_STRING};
} 
else {
    $buffer = $ENV{QUERY_STRING};
}
my @pairs = split(/&/, $buffer);
my $pair;

foreach $pair(@pairs) {
    (my $key, my $value) = split(/=/, $pair);
    $value =~ tr/+/ /;
    $value =~ s/%0D%0A/"%0A"/eg;
    $value =~ s/%([A-Fa-f0-9]{2})/pack("C",hex($1))/eg;
    if (defined $params{$key}) {
	$params{$key} .= "\t$value";
    } 
    else {
	$params{$key} = $value;
    }
}

my $conn = 1;
my $stringtoparse = $params{"xml"};
if(defined $params{"type"}) {
    if($params{"type"} eq "conn") {
	$conn = 1;
    }
    else {$conn = 0;}	
}

$|=1;
print "[OK]\n" if(!$conn);
$|=0;

if($dolog) {
	dolog("/tmp/connection.log",$params{"xml"},">");
}

# --- Create Answer XML File and append <data>
my $doc2 = new XML::DOM::Document;
my $data2 = $doc2->createElement("data");
$doc2->appendChild($data2);

if ( $stringtoparse ne "" ) {

    my $parser = new XML::DOM::Parser;
    my $doc = $parser->parse($stringtoparse);
    
    my $data = $doc->getElementsByTagName("data");

    if ( $data->getLength > 0) {

		my $tasks=$data->item(0)->getElementsByTagName("task");
		
		if($data->item(0)->getElementsByTagName("port")->getLength > 0 and 
		$data->item(0)->getElementsByTagName("device")->getLength > 0) {
			my $devicetype = $data->item(0)->getElementsByTagName("device")->item(0)->getAttribute("type");
			my $porttype = $data->item(0)->getElementsByTagName("port")->item(0)->getAttribute("type");
			if($porttype eq "IPPort" and 
				!(substr($devicetype, 0, 3) eq "CDM" or
				$devicetype eq "TERMINAL" or
				$devicetype eq "TERRASAT" or
				$devicetype eq "PARADISEPA" or
				$devicetype eq "SSPAP400" or
				$devicetype eq "Ping" or
				$devicetype eq "P3000" or
				$devicetype eq "RCP2" or
				$devicetype eq "LPOD" or
				$devicetype eq "Novelsat" or
				$devicetype eq "VERTEXRSI7200"
				)) 
			{
				my $command = processSNMP($tasks);
				exit(0);
			}
		}

		my $originals=$data->item(0)->getElementsByTagName("original"); 
		for(my $i = 0; $i < $tasks->getLength; $i++) {
		    my $task2=$doc2->createElement("task");
		    $data2->appendChild($task2);
		    if($tasks->item($i)->getElementsByTagName("pause")->getLength == 1) {
				sleep($tasks->item($i)->getElementsByTagName("pause")->item(0)->getChildNodes->item(0)->getNodeValue);
		    }
            my $sockin = formRequest($tasks, $i);	# set of tasks and task number

			my $sock = IO::Socket::INET->new(Proto=>"tcp", PeerAddr=>$host, PeerPort=>$port)
    	            or die "Can't connect to port $port on $host: $!";
            $sock->autoflush(1);

		    print $sock $sockin;

		    my $getset = "";
		    my $parname = "";
		    my $parvalue = "";
		    my $parstatus = "";

		    while( <$sock> ) {
				chomp;
			
				$getset = $parname = $parvalue = $parstatus = "";
    
#			if($_ eq "===FINISH===") { last };
				if ( $_ =~ /([GS])et::(.*?)=(.*)\((-?\d+)\)/ ) {
				    $getset=$1."et";
				    $parname=$2;
				    $parvalue=$3;
				    $parstatus=$4;
				    if($parstatus != 0 and $getset eq "Set") {
						$rollback_flag = 1;
				    }
			
#--- Filling Answer XML with Data
	
				    my $param=$doc2->createElement("param");
				    $task2->appendChild($param);
				    $param->setAttribute("name","$parname");
				    $param->setAttribute("status","$parstatus");
				    my $cdata=$doc2->createCDATASection("cdata");
				    $cdata->setData("$parvalue");
				    $param->appendChild($cdata);
				}
				if($dolog) {
					dolog("/tmp/connection.log","$_ \t\t\t $parname=$parvalue($parstatus)\n",">>");
				}
		    }
	    	close($sock);
		    if($rollback_flag) { last };

#End of Device Section
#Print result of work.
	    }
		if($rollback_flag and $originals->getLength() > 0){
		    for(my $i = 0; $i < 2; $i++){
				for(my $i = 0; $i < $originals->getLength; $i++) {
					my $sockin = formRequest($originals, $i);
	
		    	    my $sock = IO::Socket::INET->new(Proto=>"tcp", PeerAddr=>$host, PeerPort=>$port)
		        	    or die "Can't connect to port $port on $host: $!";
	        	    $sock->autoflush(1);
	
				    print $sock $sockin;
	
				    while( <$sock> ) {
						chomp;
				        my $answer = $_;
				    }
		    		close($sock);
			    }
			}
	    }
	}
    $doc->dispose();
}


my $final = $doc2->toString();
if($dolog) {
	dolog("/tmp/connection.log",$final,">>");
}
print $final if($conn);
#$final =~  s/([^\w()'*~!.-])/sprintf '%%%02x', ord $1/eg;

$doc2->dispose();

sub processSNMP
{
  my $tasks = shift;
  my $i = 0;
  my $command = "";
  my $version = "1";
  my $result = "<data><task>";
  my $number = "";
  my $community = "public";
  my $wcommunity = "private";
  my $location = "0";
  if ( !defined($tasks) or !defined($i) )
  {
    if($dolog) {dolog("/tmp/connection.log","Error! No task specified.\n", ">>");}
    exit(1);
  }
  my $devnodes=$tasks->item($i)->getElementsByTagName("device");
  if ( $devnodes->getLength == 1 )
  {
    my $devnode=$devnodes->item(0);
    my $devtype = $devnode->getAttribute("type");
    my $devparams=$devnode->getElementsByTagName("parameter");		
    my $devparams_number = $devparams->getLength;
    my $address = "";
    for(my $i=0; $i<$devparams_number; $i++)
    {
      my $param=$devparams->item($i);
      my $name=$param->getAttribute("name");
      my $value=$param->getChildNodes->item(0)->getData;
      if($name eq "Community") {$community = $value;}
      if($name eq "WCommunity") {$wcommunity = $value;}
      if($name eq "Address") {$address = $value;}
      if($name eq "Number") {$number = $value;}
      if($name eq "Location") {$location = $value;}
      if($name eq "SNMPVersion") {$version = $value;}
    }
    $command .= " -v $version $address ";
  }

  my $set = $tasks->item($i)->getElementsByTagName("set");
  if ( $set->getLength == 1 )
  {
    my $setparams = $set->item(0)->getElementsByTagName("param");
    my $setparams_number = $setparams->getLength;
    $command = "$command";
    for ( my $i = 0; $i < $setparams_number; $i++ )
    {
      my $param=$setparams->item($i);
      my $name=$param->getAttribute("name");
      my $changed=$param->getAttribute("changed");
      if($location eq "1") {
      	$name =~ s/6247.34/6247.52/;	#Remote CDM625
      }
      if ( $changed eq "" )
      {
        $changed = "yes";
      }    
      my $value = "";
      if ( $param->getChildNodes()->getLength != 0 )
      {
        $value = $param->getChildNodes->item(0)->getData;
      }
      my $type = `snmpget -Ov -c $community $command $name`;
      if($dolog) {dolog("/tmp/connection.log", "param $type", ">>");}
      if(index($type, "INTEGER") != -1) {$type = "i"}
      elsif(index($type, "IpAddress") != -1 or index($type, "IPADDRESS") != -1) {$type = "a"}
      elsif(index($type, "Gauge32") != -1 or index($type, "GAUGE32") != -1) {$type = "u"}
      elsif(index($type, "STRING") != -1) {$type = "s"; $value = "\"$value\"";}
      else{$type = "s"; $value = "\"$value\"";}
      if($dolog) {dolog("/tmp/connection.log", "snmpset -Ovq -c $wcommunity $command $name $type $value", ">>");}
      my $answer = `snmpset -Ovq -c $wcommunity $command $name $type $value`;
      my $status = $?;
      if($status != 0) {
        $status = -1;
        $answer = "0";
      }
      if($location eq "1") {
      	$name =~ s/6247.52/6247.34/;	#Reverse OID swap for Remote CDM625
      }
      $result .= "<param name=\"$name\" status=\"${status}\"><![CDATA[${answer}]]></param>";
    }
  }

  my $get = $tasks->item($i)->getElementsByTagName("get");
  if ( $get->getLength == 1 )
  {
    my $getparams = $get->item(0)->getElementsByTagName("param");
    my $getparams_number = $getparams->getLength;
    $command = "snmpget -Ovq -c $community" . $command;
    for ( my $i = 0; $i < $getparams_number; $i++ )
    {
      my $param = $getparams->item($i);
      my $name = $param->getAttribute("name");
      if($location eq "1") {
      	$name =~ s/6247.34/6247.52/;	#Remote CDM625
      }
      $name .= $number;	
      my $answer = `$command $name`;
      my $status = $?;
      chomp $answer;
      $answer =~ s/\"//g;
      if($status != 0) {
        $status = -1;
        $answer = "0";
      }
      #special cases:
      else{
      	#MDM6000 modem, Rx Offset
      	if($name eq ".1.3.6.1.4.1.5835.5.2.3300.1.5.1.9.1" or
      		$name eq ".1.3.6.1.4.1.5835.5.2.3300.1.5.1.5.1") {
			my @bytes = split(" ", $answer);
			@bytes = map (hex, @bytes);
			my $float = unpack 'f', pack 'C4', reverse @bytes;
			$answer = sprintf("%.1f", $float);
      	}
      }
      if($dolog) {dolog("/tmp/connection.log", "$command $name", ">>");}
      if($location eq "1") {
      	$name =~ s/6247.52/6247.34/;	#Reverse OID swap for Remote CDM625
      }
      $result .= "<param name=\"$name\" status=\"${status}\"><![CDATA[${answer}]]></param>";
    }
  }

  $result .= "</task></data>";
  print $result;
  if($dolog) {dolog("/tmp/connection.log", "$result", ">>");}
}

sub formRequest
{
  my $sockin = "";
  my $tasks = shift;
  my $i = shift;
  if ( !defined($tasks) or !defined($i) )
  {
    dolog("/tmp/connection.log","Error! No task specified.\n", ">>");
    exit(1);
  }
  my $devnodes=$tasks->item($i)->getElementsByTagName("device");
  if ( $devnodes->getLength == 1 )
  {
    my $devnode=$devnodes->item(0);
    my $devtype = $devnode->getAttribute("type");
    my $terminaltype = $devnode->getAttribute("terminalType");
    dolog("/tmp/connection.log", "TerminalType = $terminaltype\n", ">>");
    # here was ping check
    $sockin .= "Device::$devtype\n";
    if ( $devtype eq "TERMINAL" and $terminaltype ne "" )
    {
      $sockin .= "$devtype\:\:TerminalType=$terminaltype\n";
    }
    my $devparams=$devnode->getElementsByTagName("parameter");		
    my $devparams_number = $devparams->getLength;
    for(my $i=0; $i<$devparams_number; $i++)
    {
      my $param=$devparams->item($i);
      my $name=$param->getAttribute("name");
      my $value=$param->getChildNodes->item(0)->getData;
      $sockin .= "$devtype\:\:$name=$value\n";
    }
  }
  #Controller 
  elsif ( $devnodes->getLength == 0 )
  {
    $sockin .= "Device::Controller\n";
    $sockin .= "Controller::Interval=0\n";
  }
  #end of Controller

  my $portnodes=$tasks->item($i)->getElementsByTagName("port");
  if ( $portnodes->getLength == 1 )
  {
    my $portnode=$portnodes->item(0);
    my $porttype=$portnode->getAttribute("type");
    $sockin .= "Port::$porttype\n";
    my $portparams=$portnode->getElementsByTagName("parameter");		
    my $portparams_number = $portparams->getLength;
    for(my $i=0; $i<$portparams_number; $i++)
    {
      my $param=$portparams->item($i);
      my $name=$param->getAttribute("name");
      my $value=$param->getChildNodes->item(0)->getData;
      $sockin .= "$porttype\:\:$name=$value\n";
    }
  }

  my $set = $tasks->item($i)->getElementsByTagName("set");
  if ( $set->getLength == 1 )
  {
    my $setparams = $set->item(0)->getElementsByTagName("param");
    my $setparams_number = $setparams->getLength;
    for ( my $i = 0; $i < $setparams_number; $i++ )
    {
      my $param=$setparams->item($i);
      my $name=$param->getAttribute("name");
      my $changed=$param->getAttribute("changed");
      if ( $changed eq "" )
      {
        $changed = "yes";
      }    
      my $value = "";
      if ( $param->getChildNodes()->getLength != 0 )
      {
        $value = $param->getChildNodes->item(0)->getData;
      }
      $sockin .= "Set\:\:$name($changed)=$value\n";
    }
  }

  my $get = $tasks->item($i)->getElementsByTagName("get");
  if ( $get->getLength == 1 )
  {
    my $getparams = $get->item(0)->getElementsByTagName("param");
    my $getparams_number = $getparams->getLength;
    for ( my $i = 0; $i < $getparams_number; $i++ )
    {
      my $param = $getparams->item($i);
      my $name = $param->getAttribute("name");	
      $sockin .= "Get\:\:$name\n";
    }
  }

  $sockin .= "Priority\:\:Connection\n";
  $sockin .= "--------\n";

  dolog("/tmp/connection.log", "$sockin", ">>");

  return $sockin;
}
