Source for file GuiEditDevice.php

Documentation is available at GuiEditDevice.php

  1. <?php
  2. /**
  3.  * 
  4.  * GuiEditDevice.php
  5.  *
  6.  * Long description for file:
  7.  * Allow End-Device records to edited, deleted or inserted.
  8.  * Specific to the FreeNAC DB schema.
  9.  *
  10.  * @package     FreeNAC
  11.  * @author      Many: S.Boran, T.Dagonnier, P.Bizeau
  12.  * @copyright   2008 FreeNAC
  13.  * @license     http://www.gnu.org/copyleft/gpl.html   GNU Public License Version 3
  14.  * @version     SVN: $Id$
  15.  * @link        http://freenac.net
  16.  *
  17.  */
  18.  
  19.  
  20. class GuiEditDevice extends WebCommon
  21. {
  22.   private $id$action;      // See also WebCommon and Common
  23.  
  24.  
  25.   function __construct($action$id=0$debug_level=1)
  26.   {
  27.     parent::__construct(false);     // See also WebCommon and Common
  28.     $this->logger->setDebugLevel($debug_level);
  29.     $this->debug("GuiEditDevice__construct id=$id, debug=$debug_level, action=$action"2);
  30.  
  31.     // 1. verify/clean 'id'
  32.     #if ( !is_int($id) )     // must be a number
  33.     if !is_numeric($id) )     // must be a number
  34.        throw new InvalidWebInputException("invalid index: <$id> is not an integer");
  35.     //if ( $id===0 )              
  36.     //   throw new InvalidWebInputException(""GuiEditDevice__construct invalid index: zero");
  37.  
  38.     #if (isset($_REQUEST['action_idx'])) $logger->debug("action_idx=" .$_REQUEST['action_idx'], 2);
  39.     $this->id=$id;                   // remember the record number
  40.     $_SESSION['report1_index']=$id;  // for passing to other scripts: no longer used?
  41.     
  42.     // 2. verify/clean 'action'
  43.     // Now, have we a REQUEST action to carry out?
  44.     if !isset($action) ) {
  45.        throw new InvalidWebInputException("No action ");
  46.     }
  47.     $this->action=validate_webinput($action);
  48.  
  49.   }
  50.  
  51.  
  52.   public function print_title($title)
  53.   {
  54.     echo $this->print_header();
  55.     echo "<div id='GuiList1Title'>{$title}</div>";
  56.     //$this->debug($_SESSION['login_data'] .":Id=$id:" , 1);
  57.   }
  58.  
  59.  
  60.   public function handle_request()
  61.   {
  62.     $action=$this->action;
  63.     #global $_SESSION, $_REQUEST;
  64.     #$_REQUEST=array_map('validate_webinput',$_REQUEST);
  65.     $this->debug("handle_request() $action"2);
  66.  
  67.     if (isset($action)) {
  68.       if ($action==='Update'{
  69.         $this->print_title('Update End-Device Details');
  70.         #$logger->debug("action=$action, report1_index=" .$_SESSION['report1_index'], 1);
  71.         echo $this->Update();
  72.         echo $this->query();
  73.         echo $this->print_footer();
  74.  
  75.       else if ($action==='Edit'{
  76.         $this->print_title('Edit End-Device Details');
  77.         echo $this->query();
  78.         echo $this->print_footer();
  79.  
  80.        
  81.       else if ($action==='Add'{
  82.         if (isset($_REQUEST['name']&& isset($_REQUEST['mac']) ) {
  83.           $this->print_title('New End-Device');  // Add step2
  84.           echo $this->UpdateNew();
  85.         else {        // Add Step1
  86.           $this->print_title('Add new End-Device');
  87.           echo $this->Add();
  88.         }
  89.         echo $this->print_footer();
  90.        
  91.       else if ($action==='Delete'{
  92.         $this->print_title('Edit End-Device Details');
  93.         $this->Delete();
  94.        
  95.       else if ($action==='Restart Port'{
  96.         $this->print_title('Restart port request');
  97.         $this->RestartPort();
  98.         echo $this->print_footer();
  99.        
  100.       else {
  101.         // do nothing, action does not concern us.
  102.       }
  103.     }
  104.   }
  105.  
  106.  
  107.   public function RestartPort()
  108.   {
  109.     if ($_SESSION['nac_rights']<2)
  110.       throw new InsufficientRightsException($_SESSION['nac_rights']);
  111.     if $this->id===)              
  112.       throw new InvalidWebInputException("RestartPort() invalid index: zero");
  113.  
  114.     $conn=$this->getConnection();     //  make sure we have a DB connection
  115.     $device=$this->id;    // rely on the constructor to clean & ensure a valid id
  116.     $port_index=0;
  117.     $this->debug("RestartPort() device index {$device}"2);
  118.  
  119.     $q="SELECT LastPort FROM systems WHERE id={$device} LIMIT 1";     // only this record
  120.       $this->debug($q3);
  121.       $res $conn->query($q);
  122.       if ($res === FALSE)
  123.         throw new DatabaseErrorException($q ." :: " .$conn->error);
  124.       while (($row $res->fetch_assoc()) !== NULL{
  125.         $port_index=$row['LastPort'];
  126.       }
  127.  
  128.  
  129.     if $this->port_restart_request($port_index) ) {
  130.       $txt=<<<TXT
  131.       <p class='UpdateMsgOK'>The Switch Port ${port_index} will be restarted within one minute</p>
  132.       <p>To followup, <a href='logserver.php'>view the serverlog</a> for a confirmation, or go
  133.       <a HREF='javascript:javascript:history.go(-1)'>back to the previous screen</a>,  </div>
  134. TXT;
  135.     else {
  136.       $txt=<<<TXT
  137.       <p class='UpdateMsg'>The Switch Port  canot be restarted as it is invalid.</p>
  138.       <p>Please go <a HREF='javascript:javascript:history.go(-1)'>back to the previous screen</a>,  </div>
  139. TXT;
  140.     }
  141.     echo $txt;
  142.   }
  143.  
  144.  
  145.  
  146.   public function Delete()
  147.   {
  148.     if ($_SESSION['nac_rights']<2)
  149.       throw new InsufficientRightsException($_SESSION['nac_rights']);
  150.     if $this->id===)              
  151.       throw new InvalidWebInputException("Delete() invalid index: zero");
  152.  
  153.     $conn=$this->getConnection();     //  make sure we have a DB connection
  154.     #var_dump($_REQUEST);
  155.     $device=$this->id;    // rely on the constructor to clean & ensure a valid id
  156.     $this->debug("Delete() index {$device}"3);
  157.  
  158.     $q="DELETE FROM systems WHERE id={$device} LIMIT 1";     // only this record
  159.       $this->debug($q3);
  160.       $res $conn->query($q);
  161.       if ($res === FALSE)
  162.         throw new DatabaseErrorException($q ." :: " .$conn->error);
  163.  
  164.       // Inform the user that is was OK
  165.       $txt=<<<TXT
  166. <p class='UpdateMsgOK'>Delete Successful</p>
  167.  <br><p > Go back to the <a href="{$_SESSION['caller']}">End-Device list</a></p>
  168. </div>
  169. TXT;
  170.       echo $txt;
  171.       $this->logit("Deleted system with Index {$device}");
  172.       $this->loggui("Deleted system with Index {$device}");
  173.  
  174.   }
  175.  
  176.  
  177.  
  178.   /**
  179.    * Insert a newrecord
  180.    */
  181.   public function UpdateNew()
  182.   {
  183.     $this->debug("UpdateNew()"3);
  184.     #var_dump($_REQUEST);
  185.  
  186.     if ($_SESSION['nac_rights']<2)
  187.       throw new InsufficientRightsException($_SESSION['nac_rights']);
  188.     $conn=$this->getConnection();     //  make sure we have a DB connection
  189.  
  190.     #echo "<p class='UpdateMsg'>Insert Pending</p>";
  191.     #$this->id
  192.  
  193.     try {
  194.       // Read in request variables. Mac and name are set, others are optional
  195.       // TBD: call validate_input?
  196.       $name=trim($_REQUEST['name']);            // get rid of leading/trailing spaces
  197.       $mac=strtolower($_REQUEST['mac']);        // lower case by convention
  198.       $mac=$this->sqlescape($mac);             // TBD: verify syntax/length etc.
  199.       $name=$this->sqlescape($name);           
  200.       $q="INSERT INTO systems SET mac='$mac', name='$name";
  201.  
  202.      if isset($_REQUEST['comment']) )
  203.         $q.=", comment='" .$this->sqlescape($_REQUEST['comment']."'";
  204.      if (( isset($_REQUEST['status']) ) && is_numeric ($_REQUEST['status']) )
  205.         $q.=", status="  .$_REQUEST['status';
  206.  
  207.  
  208.      if ( ( isset($_REQUEST['vlan']) ) && is_numeric ($_REQUEST['vlan']) ){  // re-verify vlan assignment right
  209.         // Restrict vlan for superusers?
  210.         if !empty($_SESSION['GuiVlanRights']&& ($_SESSION['nac_rights']==2)) {
  211.           $this->debug("Web user {$_SESSION['uid']} has restricted vlans: {$_SESSION['nac_rights']}"1);
  212.           $vlans_allowed explode(','$_SESSION['GuiVlanRights']);
  213.           if (array_search($_REQUEST['vlan']$vlans_allowed) ) {
  214.              $q.=', vlan='  .$_REQUEST['vlan'];
  215.           }
  216.           else {
  217.              $this->logger->logit("Web user {$_SESSION['uid']} is not allowed to assign vlan {$_REQUEST['vlan']} only {$_SESSION['GuiVlanRights']}");
  218.           }
  219.         }
  220.         else {    // no restrictions
  221.           $this->debug("Web user {$_SESSION['uid']} is allowed to assign any vlan:  vlan idx="  .$_REQUEST['vlan']3);
  222.           $q.=', vlan='  .$_REQUEST['vlan'];
  223.         }
  224.      }
  225.  
  226.       $this->debug("UpdateNew() $q"3);
  227.       $res $conn->query($q);
  228.       if ($res === FALSE)
  229.         throw new DatabaseInsertException($conn->error);
  230.  
  231.       echo "<p class='UpdateMsgOK'>Successful: new end-device $name/$mac added</p>";
  232.       #echo "<p class='UpdateMsgOK'>Now view/update the end-device details</p>";
  233.  
  234.       // after inserting, locate that record, and show the Update() screen.
  235.       $res $conn->query("SELECT id,name from systems where mac='" .$mac ."'");
  236.       if ($res === FALSE)
  237.         throw new DatabaseErrorException($conn->error);
  238.       while (($row $res->fetch_assoc()) !== NULL{
  239.         $this->id=$row['id'];
  240.       }
  241.       $_SESSION['report1_index']=$this->id;  // for passing to other scripts
  242.  
  243.       $this->loggui("new end-device $name, mac=$mac, index=$this->id added");
  244.  
  245.       // locate that record, and show the Update() screen.
  246.       $ref=$this->calling_script"?action=Edit&action_idx=$this->id";
  247.       #echo $ref;
  248.       #$this->debug($ref); 
  249.       echo "<p class='UpdateMsgOK'>Now review/update the <a href='$ref'>end-device details</a></p>";
  250.  
  251.     catch (Exception $e{
  252.       throw $e;
  253.     }
  254.  
  255.  }
  256.  
  257.  
  258.  
  259.   /**
  260.    * Update a record: read fields/data from the POST, generate SQL and execute
  261.    */
  262.   public function Update()
  263.   {
  264.     $this->debug("Update()"3);
  265.     #var_dump($_REQUEST);
  266.     if ($_SESSION['nac_rights']<2)
  267.       throw new InsufficientRightsException('Update() ' .$_SESSION['nac_rights']);
  268.     $conn=$this->getConnection();     //  make sure we have a DB connection
  269.  
  270.     // Clean inputs from the web, (security). Use _REQUEST to
  271.     // allow both GET (automation) or POST (interactive GUIs)
  272.     $_REQUEST=array_map('validate_webinput',$_REQUEST);
  273.     if (!isset($_REQUEST['action_idx']) )
  274.       throw new InvalidWebInputException("Update() action_idx not set");
  275.     if !is_numeric($_REQUEST['action_idx']|| $_REQUEST['action_idx']==0)     // must be a number>0
  276.        throw new InvalidWebInputException("invalid index: is not an integer");
  277.  
  278.     $this->id=$_REQUEST['action_idx'];
  279.  
  280.     try {
  281.       $q='';
  282.         $q='UPDATE systems SET ';
  283.         // got name?
  284.         $q.=($_REQUEST['name']!='' 'name=\'' .$_REQUEST['name'.'\' ' '');
  285.         // status, user, office, comment
  286.         $q.=', status='.$_REQUEST['status'];
  287.         $q.=($_REQUEST['username']!='' ', uid='.$_REQUEST['username'].' ' '');
  288.         $q.=($_REQUEST['office']!='' ', office='.$_REQUEST['office'].'' '');
  289.         $q.=($_REQUEST['sys_class']!='' ', class=\''.$_REQUEST['sys_class'].'\'' '');
  290.         $q.=($_REQUEST['sys_class2']!='' ', class2=\''.$_REQUEST['sys_class2'].'\'' '');
  291.         # allow empty values
  292.         $q.=(', expiry=\''.$_REQUEST['expiry'].'\'');   
  293.         $q.=(', email_on_connect=\''.$_REQUEST['email_on_connect'].'\'');   
  294.         $q.=(', inventory=\''.$_REQUEST['inventory'].'\'');   
  295.         $q.=(', comment=\''.$_REQUEST['comment'].'\'');   
  296.  
  297.         // TBD: DNS Alias & DHCP
  298.         if ($this->conf->web_showdns{
  299.           // TODO : validate DNS aliases
  300.           $q.=", dns_alias='".$_REQUEST['dns_alias']."'";
  301.         }
  302.         if ($this->conf->web_showdhcp{
  303.           // TODO : validate dhcp_ip as ip address
  304.           if (($_REQUEST['dhcp_fix'== 'dhcp_fix'&& ($_REQUEST['dhcp_ip'!= '')) {
  305.             $q.=", dhcp_fix=1, dhcp_ip='".$_REQUEST['dhcp_ip']."'";
  306.           }
  307.         }
  308.  
  309.         // Restrict vlan for superusers?
  310.         if !empty($_SESSION['GuiVlanRights']&& ($_SESSION['nac_rights']==2)) {
  311.           $this->debug("Web user {$_SESSION['uid']} has restricted vlans: {$_SESSION['nac_rights']}"1);
  312.           $vlans_allowed explode(','$_SESSION['GuiVlanRights']);
  313.           if (array_search($_REQUEST['vlan']$vlans_allowed) ) {
  314.              $q.=', vlan='  .$_REQUEST['vlan'];
  315.           }
  316.           else {
  317.              $this->logger->logit("Web user {$_SESSION['uid']} is not allowed to assign vlan {$_REQUEST['vlan']}");
  318.           }
  319.         }
  320.         else {    // no restrictions
  321.           $this->debug("Web user {$_SESSION['uid']} is allowed to assign any vlan"2);
  322.           $q.=', vlan='  .$_REQUEST['vlan'];
  323.         }
  324.  
  325.         // Log who made the change, when: 
  326.         if (is_numeric($_SESSION['uid'])) $q.=", changeuser={$_SESSION['uid']}";
  327.         $q.=", changedate=NOW()";
  328.         $q.=" WHERE id={$this->id} LIMIT 1";     // only this record
  329.       $this->debug($q3);
  330.       #$this->logit($q);
  331.       $res $conn->query($q);
  332.       if ($res === FALSE)
  333.         throw new DatabaseErrorException($conn->error);
  334.  
  335.       echo "<p class='UpdateMsgOK'>Update Successful</p>";
  336.       $this->loggui("end-device " .$_REQUEST['name'."/" .$_REQUEST['mac'." updated");
  337.  
  338.     } catch (Exception $e) {
  339.       throw $e;
  340.     }
  341.   }
  342.  
  343.  
  344.   /**
  345.    * Add a new device: Query a record and display on the WebGUI
  346.    */
  347.   public function add()
  348.   {
  349.     global $js1;
  350.     if ($_SESSION['nac_rights']<2)    // must have edit rights
  351.       throw new <a href="../FreeNAC/InsufficientRightsException.html">InsufficientRightsException</a>($_SESSION['nac_rights']);
  352.  
  353.     $conn=$this->getConnection();     //  make sure we have a DB connection
  354.     $this->debug("EditDevice::Add() ", 3);
  355.     #$output ='<form name="formadd" action="GuiEditDevice_control.php" method="POST">';
  356.     $output ='<form name="formadd" action="' .$_SERVER['PHP_SELF'] .'" method="POST">';
  357.     $output.= "\n$js1\n <table id='GuiEditDeviceAdd'>";
  358.  
  359.     $name=''; $mac='0001.0001.0001'; 
  360.     try {
  361.  
  362.         // Name, MAC
  363.         $output.=<<<TXT
  364.         <tr><td width="87" title="What name is to be used by FreeNAC to reference this device?">Name:</td>
  365.             <td width="400"> <input name="name" type="text" value="{$name}" onBlur="checkLen(this,1)">
  366.         </td></tr>
  367.         <tr><td width="87"  title="Enter a valid 12 digit hex MAC address, in the format xxxx.yyyy.zzzz ">MAC:</td>
  368.             <td width="400"> <input name="mac" type="text" value="{$mac}" onBlur="checkLen(this,14) ">
  369.         </td></tr>
  370. TXT;
  371.         // Status
  372.         $output.=  '<tr><td title="Is the new device to be allowed on the network">Status:</td><td>'."\n";
  373.         $output.=  $this->get_statusdropdown(1) . '</td></tr>'."\n";
  374.         // VLAN, last vlan/date
  375.         $output.= "<tr><td title='What vlan to be assigned to this device?'>VLAN: </td><td>\n"
  376.           . $this->get_vlandropdown($this->conf->default_vlan) . '</td>';
  377.  
  378.       $output.=<<<TXT
  379.         <tr><td></td><td>
  380.         <input type="submit" class="bluebox" name="action" value="Add" onclick="return checkForm()"
  381.         title="Click to add a new device with the above details"/>
  382.     </td>
  383.         </form>
  384.     </table>
  385. TXT;
  386.  
  387.     } catch (Exception $e) {
  388.       throw $e;
  389.     }
  390.     return($output);
  391.   }                               // function
  392.  
  393.  
  394.  
  395.   /**
  396.    * Display a device record, allow changes.
  397.    * Next Step is Either Update, Delete, or Restart Port
  398.    */
  399.   public function query()
  400.   {
  401.     if ($_SESSION['nac_rights']<2)
  402.       throw new <a href="../FreeNAC/InsufficientRightsException.html">InsufficientRightsException</a>($_SESSION['nac_rights']);
  403.     $conn=$this->getConnection();     //  make sure we have a DB connection
  404.     #$output ='<form action="GuiEditDevice_control.php" method="POST">';
  405.     $output ='<form action="'.$_SERVER['PHP_SELF'].'" method="POST">';
  406.     #$output ='<form action="'.$_SERVER['PHP_SELF'].'" method="GET">'; /i/debugging
  407.     $output.="<table id='t3' width='760' border='0' class='text13'>";
  408.  
  409. $q=<<<TXT
  410. SELECT sys.id, sys.name, sys.mac, sys.status, sys.vlan, lvlan.default_name as lastvlan, sys.uid as user, sys.office, port.name as port, sys.lastseen, swloc.name as location, swi.name as switch, sys.r_ip as lastip, sys.r_timestamp as lastipseen, sys.comment, eth.vendor, dns_alias, dhcp_fix, dhcp_ip, inventory, class, class2, email_on_connect, expiry
  411.                         FROM systems as sys LEFT JOIN vlan as lvlan ON sys.lastvlan=lvlan.id LEFT JOIN port as port ON port.id=sys.lastport LEFT JOIN switch as swi ON port.switch=swi.id LEFT JOIN location as swloc ON swloc.id=swi.location LEFT JOIN ethernet as eth ON (SUBSTR(sys.mac,1,4)=SUBSTR(eth.mac,1,4) AND SUBSTR(sys.mac,6,2)=SUBSTR(eth.mac,5,2))
  412.   WHERE sys.id=$this->id
  413.   LIMIT 1
  414. TXT;
  415.  
  416.     try {
  417.       $this->debug("EditDevice::query() $q", 3);
  418.       $res = $conn->query($q);
  419.       if ($res === FALSE)
  420.         throw new DatabaseErrorException($conn->error);
  421.  
  422.       // Title: Grab the list of field names
  423.       $fields=$res->fetch_fields();
  424.       #  foreach ($fields as $field) {
  425.       #    $fname=$field->name;
  426.       #    $output.="<tr><td>$fname</td><td>{$row[$fname]}</td></tr>";
  427.       #  }
  428.       while (($row = $res->fetch_assoc()) !== NULL) {
  429.         #$this->debug(var_dump($row), 3);
  430.         // Name
  431.         $output.= '<tr><td width="87">Name:</td><td width="400">' ."\n";
  432.         $output.= '<input name="name" type="text" value="' .stripslashes($row['name']) .'"/>' ."\n";
  433.         $output.= '</td><td>Index:' .$row['id'] .'</td>' ."</tr>\n";
  434.         // MAC
  435.         $output.= '<tr><td>MAC:</td><td>' ."\n";
  436.         $output.= $row['mac'] .(!is_null($row['vendor'])?' (' .$row['vendor'] .')':'') ."\n";
  437.         $output.= '</td></tr>'."\n";
  438.         $output.= '<input type="hidden" name="mac" value="' .$row['mac'] .'" />' ."\n";
  439.         // Status
  440.         $output.=  '<tr><td>Status:</td><td>' ."\n";
  441.         $output.=  $this->get_statusdropdown($row['status']) . '</td></tr>'."\n";
  442.  
  443.         // VLAN, last vlan/date
  444.         $output.= "<tr><td>VLAN: </td><td>\n"
  445.           . $this->get_vlan($row['vlan']) ."  "
  446.           . $this->get_vlandropdown($row['vlan']) . '</td> <td>Last VLAN:'
  447.           . (is_null($row['lastvlan']) ? 'NONE' : $row['lastvlan'])
  448.           .  '<br>' .$row['lastseen'] .'</td>' ."\n";
  449.  
  450.         // User, location, switch, comment, last IP/date
  451.         $output.= '<tr><td>User:</td><td>' ."\n"
  452.           . $this->get_userdropdown($row['user'])
  453.           . '</td></tr>' ."\n";
  454.         $output.= '<tr><td>Location:</td><td>' ."\n"
  455.           . $this->get_officedropdown($row['office'])
  456.           . '</td></tr>' ."\n";
  457.  
  458.        &