<?php

class Routerboard
{
  var $SSHPath = '/usr/bin/ssh';
  var $Timeout = 3;
  var $HostName;
  var $UserName;
  var $Password;
  var $PrivateKey = 'id_dsa';
  var $MaxBurstLineCount = 100;
  var $Debug = false;

  function __construct($HostName = 'localhost', $UserName = 'admin', $Password = '')
  {
    $this->HostName = $HostName;
    $this->UserName = $UserName;
    $this->Password = $Password;
  }

  function Execute($Commands)
  {
    $Output = array();
    if(is_array($Commands))
    {
      $I = 0;
      $Batch = array();
      while($I < count($Commands))
      {
        if(($I % $this->MaxBurstLineCount) == 0)
        {
          if(count($Batch) > 0)
            $Output = array_merge($Output, $this->ExecuteBatch(implode(';', $Batch)));
          $Batch = array();
        }
        $Batch[] = $Commands[$I];
        $I++;
      }
      if(count($Batch) > 0)
       $Output = array_merge($Output, $this->ExecuteBatch(implode(';', $Batch)));
    } else 
      $Output = array_merge($Output, $this->ExecuteBatch($Commands));
    return($Output);
  }
  
  function ExecuteBatch($Commands)
  {    
    $Commands = trim($Commands);
    if($Commands != '')
    {
      $Commands = addslashes($Commands);
      $Commands = str_replace('$', '\$', $Commands);
      //$Commands = str_replace(' ', '\ ', $Commands);  
      $Command = $this->SSHPath.' -o ConnectTimeout='.$this->Timeout.' -l '.$this->UserName.' -i '.$this->PrivateKey.' '.$this->HostName.' "'.$Commands.'"';
      if($this->Debug) echo($Command);
      $Output = array();
      exec($Command, $Output);
    } else $Output = '';
    if($this->Debug) print_r($Output);
    return($Output);
  }

  function ItemGet($Path)
  {
    $Result = $this->Execute(implode(' ', $Path).' print');
    array_pop($Result);
    $List = array();
    foreach($Result as $ResultLine)
    {
      $ResultLineParts = explode(' ', trim($ResultLine));
      if(count($ResultLineParts) > 1)
      {
        if($ResultLineParts[1]{0} == '"') $ResultLineParts[1] = substr($ResultLineParts[1], 1, -1); // Remove quotes
        $List[substr($ResultLineParts[0], 0, -1)] = $ResultLineParts[1];
      } else $List[substr($ResultLineParts[0], 0, -1)] = '';
    }
    return($List);
  }

  function ListGet($Path, $Properties, $Conditions = array())
  {
    $PropertyList = '"';
    foreach($Properties as $Index => $Property)
    {
      $PropertyList .= $Index.'=".[get $i '.$Property.']." ';
    }
    $PropertyList = substr($PropertyList, 0, -3);

    $ConditionList = '';
    foreach($Conditions as $Index => $Item)
    {
      if($Item == 'no') $ConditionList .= $Index.'='.$Item.' ';
      else $ConditionList .= $Index.'="'.$Item.'" ';
    }
    $ConditionList = substr($ConditionList, 0, -1);

    $Result = $this->Execute(implode(' ', $Path).' {:foreach i in=[find '.$ConditionList.'] do={:put ('.$PropertyList.')}}');
    $List = array();
    foreach($Result as $ResultLine)
    {
      $ResultLineParts = explode(' ', $ResultLine);
      $ListItem = array();
      foreach($ResultLineParts as $ResultLinePart)
      {
        $Value = explode('=', $ResultLinePart);
        if(count($Value) > 1) $ListItem[$Properties[$Value[0]]] = $Value[1];
          else $ListItem[$Properties[$Value[0]]] = '';
      }
      $List[] = $ListItem;
    }
    return($List);
  }

  function ListGetPrint($Path, $Properties, $Conditions = array())
  {
    $ConditionList = '';
    foreach($Conditions as $Index => $Item)
    {
      $ConditionList .= $Index.'="'.$Item.'" ';
    }
    $ConditionList = substr($ConditionList, 0, -1);
    if(trim($ConditionList) != '')
      $ConditionList = ' where '.$ConditionList;    

    $Result = $this->Execute(implode(' ', $Path).' print terse'.$ConditionList);
    $List = array();
    foreach($Result as $ResultLine)
    {
      $ResultLineParts = explode(' ', $ResultLine);
      $ListItem = array();
      foreach($ResultLineParts as $ResultLinePart)
      {
        $Value = explode('=', $ResultLinePart);
        if(in_array($Value[0], $Properties))
        {
          if(count($Value) > 1) 
          {
            if($Value[1]{0} == '"') $Value[1] = substr($Value[1], 1, -1);            
            //if(strlen($Value[1]) > 0)
            $ListItem[$Value[0]] = $Value[1];
          } else $ListItem[$Value[0]] = '';
        }
      }
      if(count($ListItem) > 0) $List[] = $ListItem;
    }
    return($List);
  }

  function ListEraseAll($Path)
  {
    $this->Execute(implode(' ', $Path).' { remove [find] }');
  }
  
  function ListUpdate($Path, $Properties, $Values, $Condition = array(), $UsePrint = false)
  {
    // Get current list from routerboard
    if($UsePrint == 0) 
    {
      $List = $this->ListGet($Path, $Properties, $Condition);
      // Change boolean values yes/no to true/false
      foreach($List as $Index => $ListItem)
      {
        foreach($ListItem as $Index2 => $Item2)
        {
          if($Item2 == 'true') $List[$Index][$Index2] = 'yes';
          if($Item2 == 'false') $List[$Index][$Index2] = 'no';
        }
      }
    } else 
    {
      $List = $this->ListGetPrint($Path, $Properties, $Condition);     
    }
    $Commands = array();
    
    // Add empty properties to values
    foreach($Values as $Index => $Item)
    {
      foreach($Properties as $Property)
      {
        if(!array_key_exists($Property, $Item))
           $Item[$Property] = '';
      }
      $Values[$Index] = $Item;      
    }
    foreach($List as $Index => $Item)
    {
      foreach($Properties as $Property)
      {
        if(!array_key_exists($Property, $Item))
           $Item[$Property] = '';
      }
      $List[$Index] = $Item;      
    }
    
    // Sort properties
    foreach($Values as $Index => $Item)
    {
      ksort($Values[$Index]);
    }
    foreach($List as $Index => $Item)
    {
      ksort($List[$Index]);
    }
    if($this->Debug) print_r($List);
    if($this->Debug) print_r($Values);
       
    // Erase all items not existed in $Values
    foreach($List as $Index => $ListItem)
    {
      if(!in_array($ListItem, $Values))
      {
        $Prop = '';
        foreach($ListItem as $Index => $Property)
        {
          if($Property != '') 
          {
            if(($Property == 'yes') or ($Property == 'no')) $Prop .= $Index.'='.$Property.' ';
              else $Prop .= $Index.'="'.$Property.'" ';
          }
        }
        $Prop = substr($Prop, 0, -1);
        if(trim($Prop) != '')
          $Commands[] = implode(' ', $Path).' remove [find '.$Prop.']';
      }
    }
    
    // Add new items
    foreach($Values as $ListItem)
    {
      if(!in_array($ListItem, $List))
      {
        $Prop = '';
        foreach($ListItem as $Index => $Property)
        {
          if($Property != '') $Prop .= $Index.'="'.$Property.'" ';
        }
        $Prop = substr($Prop, 0, -1);
        $Commands[] = implode(' ', $Path).' add '.$Prop;
      }
    }
    if($this->Debug) print_r($Commands);
    return($this->Execute($Commands));    
  }
}
