Net
[ class tree: Net ] [ index: Net ] [ all elements ]

Source for file Ping.php

Documentation is available at Ping.php

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Martin Jansen <mj@php.net>                                  |
  17. // |          Tomas V.V.Cox <cox@idecnet.com>                             |
  18. // |          Jan Lehnardt  <jan@php.net>                                 |
  19. // |          Kai Schrder <k.schroeder@php.net>                          |
  20. // |          Craig Constantine <cconstantine@php.net>                    |
  21. // +----------------------------------------------------------------------+
  22. //
  23. // $Id: Ping.php 274728 2009-01-27 20:14:00Z cconstantine $
  24.  
  25. require_once "PEAR.php";
  26. require_once "OS/Guess.php";
  27.  
  28. define('NET_PING_FAILED_MSG',                     'execution of ping failed'        );
  29. define('NET_PING_HOST_NOT_FOUND_MSG',             'unknown host'                    );
  30. define('NET_PING_INVALID_ARGUMENTS_MSG',          'invalid argument array'          );
  31. define('NET_PING_CANT_LOCATE_PING_BINARY_MSG',    'unable to locate the ping binary');
  32. define('NET_PING_RESULT_UNSUPPORTED_BACKEND_MSG''Backend not Supported'           );
  33.  
  34. define('NET_PING_FAILED',                     0);
  35. define('NET_PING_HOST_NOT_FOUND',             1);
  36. define('NET_PING_INVALID_ARGUMENTS',          2);
  37. define('NET_PING_CANT_LOCATE_PING_BINARY',    3);
  38. define('NET_PING_RESULT_UNSUPPORTED_BACKEND'4);
  39.  
  40.  
  41. /**
  42. * Wrapper class for ping calls
  43. *
  44. * Usage:
  45. *
  46. * <?php
  47. *   require_once "Net/Ping.php";
  48. *   $ping = Net_Ping::factory();
  49. *   if(PEAR::isError($ping)) {
  50. *     echo $ping->getMessage();
  51. *   } else {
  52. *     $ping->setArgs(array('count' => 2));
  53. *     var_dump($ping->ping('example.com'));
  54. *   }
  55. * ?>
  56. *
  57. @author   Jan Lehnardt <jan@php.net>
  58. @version  $Revision: 274728 $
  59. @package  Net
  60. @access   public
  61. */
  62. class Net_Ping
  63. {
  64.     /**
  65.     * Location where the ping program is stored
  66.     *
  67.     * @var string 
  68.     * @access private
  69.     */
  70.     var $_ping_path "";
  71.  
  72.     /**
  73.     * Array with the result from the ping execution
  74.     *
  75.     * @var array 
  76.     * @access private
  77.     */
  78.     var $_result = array();
  79.  
  80.     /**
  81.     * OS_Guess instance
  82.     *
  83.     * @var object 
  84.     * @access private
  85.     */
  86.     var $_OS_Guess "";
  87.  
  88.     /**
  89.     * OS_Guess->getSysname result
  90.     *
  91.     * @var string 
  92.     * @access private
  93.     */
  94.     var $_sysname "";
  95.  
  96.     /**
  97.     * Ping command arguments
  98.     *
  99.     * @var array 
  100.     * @access private
  101.     */
  102.     var $_args = array();
  103.  
  104.     /**
  105.     * Indicates if an empty array was given to setArgs
  106.     *
  107.     * @var boolean 
  108.     * @access private
  109.     */
  110.     var $_noArgs = true;
  111.  
  112.     /**
  113.     * Contains the argument->option relation
  114.     *
  115.     * @var array 
  116.     * @access private
  117.     */
  118.     var $_argRelation = array();
  119.  
  120.     /**
  121.     * Constructor for the Class
  122.     *
  123.     * @access private
  124.     */
  125.     function Net_Ping($ping_path$sysname)
  126.     {
  127.         $this->_ping_path $ping_path;
  128.         $this->_sysname   $sysname;
  129.         $this->_initArgRelation();
  130.     /* function Net_Ping() */
  131.  
  132.     /**
  133.     * Factory for Net_Ping
  134.     *
  135.     * @access public
  136.     */
  137.     function factory()
  138.     {
  139.         $ping_path '';
  140.  
  141.         $sysname Net_Ping::_setSystemName();
  142.  
  143.         if (($ping_path Net_Ping::_setPingPath($sysname)) == NET_PING_CANT_LOCATE_PING_BINARY{
  144.             return PEAR::raiseError(NET_PING_CANT_LOCATE_PING_BINARY_MSGNET_PING_CANT_LOCATE_PING_BINARY);
  145.         else {
  146.             return new Net_Ping($ping_path$sysname);
  147.         }
  148.     /* function factory() */
  149.  
  150.     /** 
  151.      * Resolve the system name
  152.      *
  153.      * @access private
  154.      */
  155.     function _setSystemName()
  156.     {
  157.         $OS_Guess  = new OS_Guess;
  158.         $sysname   $OS_Guess->getSysname();
  159.  
  160.         // Refine the sysname for different Linux bundles/vendors. (This
  161.         // should go away if OS_Guess was ever extended to give vendor
  162.         // and vendor-version guesses.)
  163.         //
  164.         // Bear in mind that $sysname is eventually used to craft a
  165.         // method name to figure out which backend gets used to parse
  166.         // the ping output. Elsewhere, we'll set $sysname back before
  167.         // that.
  168.         if ('linux' == $sysname{
  169.             if (   file_exists('/etc/lsb-release')
  170.                 && false !== ($release=@file_get_contents('/etc/lsb-release'))
  171.                 && preg_match('/gutsy/i'$release)
  172.                 {
  173.                 $sysname 'linuxredhat9';
  174.             }
  175.             else if file_exists('/etc/debian_version') ) {
  176.                 $sysname 'linuxdebian';
  177.             }else if (file_exists('/etc/redhat-release')
  178.                      && false !== ($release@file_get_contents('/etc/redhat-release'))
  179.                      )
  180.             {
  181.                 if (preg_match('/release 8/i'$release)) {
  182.                     $sysname 'linuxredhat8';
  183.                 }elseif (preg_match('/release 9/i'$release)) {
  184.                     $sysname 'linuxredhat9';
  185.                 }
  186.             }
  187.         }
  188.  
  189.         return $sysname;
  190.         
  191.     /* function _setSystemName */
  192.  
  193.     /**
  194.     * Set the arguments array
  195.     *
  196.     * @param array $args Hash with options
  197.     * @return mixed true or PEAR_error
  198.     * @access public
  199.     */
  200.     function setArgs($args)
  201.     {
  202.         if (!is_array($args)) {
  203.             return PEAR::raiseError(NET_PING_INVALID_ARGUMENTS_MSGNET_PING_INVALID_ARGUMENTS);
  204.         }
  205.  
  206.         $this->_setNoArgs($args);
  207.  
  208.         $this->_args $args;
  209.  
  210.         return true;
  211.     /* function setArgs() */
  212.  
  213.     /**
  214.     * Set the noArgs flag
  215.     *
  216.     * @param array $args Hash with options
  217.     * @return void 
  218.     * @access private
  219.     */
  220.     function _setNoArgs($args)
  221.     {
  222.         if (0 == count($args)) {
  223.             $this->_noArgs = true;
  224.         else {
  225.             $this->_noArgs = false;
  226.         }
  227.     /* function _setNoArgs() */
  228.  
  229.     /**
  230.     * Sets the system's path to the ping binary
  231.     *
  232.     * @access private
  233.     */
  234.     function _setPingPath($sysname)
  235.     {
  236.         $status    '';
  237.         $output    = array();
  238.         $ping_path '';
  239.  
  240.         if ("windows" == $sysname{
  241.             return "ping";
  242.         else {
  243.             $ping_path exec("which ping"$output$status);
  244.             if (0 != $status{
  245.                 return NET_PING_CANT_LOCATE_PING_BINARY;
  246.             else {
  247.                 // be certain "which" did what we expect. (ref bug #12791)
  248.                 if is_executable($ping_path) ) {
  249.                     return $ping_path;
  250.                 }
  251.                 else {
  252.                     return NET_PING_CANT_LOCATE_PING_BINARY;
  253.                 }
  254.             }
  255.         }
  256.     /* function _setPingPath() */
  257.  
  258.     /**
  259.     * Creates the argument list according to platform differences
  260.     *
  261.     * @return string Argument line
  262.     * @access private
  263.     */
  264.     function _createArgList()
  265.     {
  266.         $retval     = array();
  267.  
  268.         $timeout    "";
  269.         $iface      "";
  270.         $ttl        "";
  271.         $count      "";
  272.         $quiet      "";
  273.         $size       "";
  274.         $seq        "";
  275.         $deadline   "";
  276.  
  277.         foreach($this->_args AS $option => $value{
  278.             if(!empty($option&& isset($this->_argRelation[$this->_sysname][$option]&& NULL != $this->_argRelation[$this->_sysname][$option]{
  279.                 ${$option$this->_argRelation[$this->_sysname][$option]." ".$value." ";
  280.              }
  281.         }
  282.  
  283.         switch($this->_sysname{
  284.  
  285.         case "sunos":
  286.              if ($size || $count || $iface{
  287.                  /* $size and $count must be _both_ defined */
  288.                  $seq " -s ";
  289.                  if ($size == ""{
  290.                      $size " 56 ";
  291.                  }
  292.                  if ($count == ""{
  293.                      $count " 5 ";
  294.                  }
  295.              }
  296.              $retval['pre'$iface.$seq.$ttl;
  297.              $retval['post'$size.$count;
  298.              break;
  299.  
  300.         case "freebsd":
  301.              $retval['pre'$quiet.$count.$ttl.$timeout;
  302.              $retval['post'"";
  303.              break;
  304.  
  305.         case "darwin":
  306.              $retval['pre'$count.$timeout.$size;
  307.              $retval['post'"";
  308.              break;
  309.  
  310.         case "netbsd":
  311.              $retval['pre'$quiet.$count.$iface.$size.$ttl.$timeout;
  312.              $retval['post'"";
  313.              break;
  314.  
  315.         case "openbsd":
  316.              $retval['pre'$quiet.$count.$iface.$size.$ttl.$timeout;
  317.              $retval['post'"";
  318.              break;
  319.  
  320.         case "linux":
  321.              $retval['pre'$quiet.$deadline.$count.$ttl.$size.$timeout;
  322.              $retval['post'"";
  323.              break;
  324.  
  325.         case "linuxdebian":
  326.              $retval['pre'$quiet.$count.$ttl.$size.$timeout;
  327.              $retval['post'"";
  328.              $this->_sysname 'linux'// undo linux vendor refinement hack
  329.              break;
  330.  
  331.         case "linuxredhat8":
  332.              $retval['pre'$iface.$ttl.$count.$quiet.$size.$deadline;
  333.              $retval['post'"";
  334.              $this->_sysname 'linux'// undo linux vendor refinement hack
  335.              break;
  336.  
  337.         case "linuxredhat9":
  338.              $retval['pre'$timeout.$iface.$ttl.$count.$quiet.$size.$deadline;
  339.              $retval['post'"";
  340.              $this->_sysname 'linux'// undo linux vendor refinement hack
  341.              break;
  342.  
  343.         case "windows":
  344.              $retval['pre'$count.$ttl.$timeout;
  345.              $retval['post'"";
  346.              break;
  347.  
  348.         case "hpux":
  349.              $retval['pre'$ttl;
  350.              $retval['post'$size.$count;
  351.              break;
  352.  
  353.         case "aix":
  354.             $retval['pre'$count.$timeout.$ttl.$size;
  355.             $retval['post'"";
  356.             break;
  357.  
  358.         default:
  359.              $retval['pre'"";
  360.              $retval['post'"";
  361.              break;
  362.         }
  363.         return($retval);
  364.     }  /* function _createArgList() */
  365.  
  366.     /**
  367.     * Execute ping
  368.     *
  369.     * @param  string    $host   hostname
  370.     * @return mixed  String on error or array with the result
  371.     * @access public
  372.     */
  373.     function ping($host)
  374.     {
  375.         
  376.         if($this->_noArgs{
  377.             $this->setArgs(array('count' => 3));
  378.         }
  379.  
  380.         $argList $this->_createArgList();
  381.         $cmd $this->_ping_path." ".$argList['pre']." ".escapeshellcmd($host)." ".$argList['post'];
  382.  
  383.         // since we return a new instance of Net_Ping_Result (on
  384.         // success), users may call the ping() method repeatedly to
  385.         // perform unrelated ping tests Make sure we don't have raw data
  386.         // from a previous call laying in the _result array.
  387.         $this->_result = array();
  388.  
  389.         exec($cmd$this->_result);
  390.  
  391.         if (!is_array($this->_result)) {
  392.             return PEAR::raiseError(NET_PING_FAILED_MSGNET_PING_FAILED);
  393.         }
  394.  
  395.         if (count($this->_result== 0{
  396.             return PEAR::raiseError(NET_PING_HOST_NOT_FOUND_MSGNET_PING_HOST_NOT_FOUND);
  397.         }
  398.         else {
  399.             // Here we pass $this->_sysname to the factory(), but it is
  400.             // not actually used by the class. It's only maintained in
  401.             // the Net_Ping_Result class because the
  402.             // Net_Ping_Result::getSysName() method needs to be retained
  403.             // for backwards compatibility.
  404.             return Net_Ping_Result::factory($this->_result$this->_sysname);
  405.         }
  406.     /* function ping() */
  407.  
  408.     /**
  409.     * Check if a host is up by pinging it
  410.     *
  411.     * @param string $host   The host to test
  412.     * @param bool $severely If some of the packages did reach the host
  413.     *                        and severely is false the function will return true
  414.     * @return bool True on success or false otherwise
  415.     *
  416.     */
  417.     function checkHost($host$severely = true)
  418.     {
  419.         $matches = array();
  420.         
  421.         $this->setArgs(array("count" => 10,
  422.                              "size"  => 32,
  423.                              "quiet" => null,
  424.                              "deadline" => 10
  425.                              )
  426.                        );
  427.         $res $this->ping($host);
  428.         if (PEAR::isError($res)) {
  429.             return false;
  430.         }
  431.         if ($res->_received == 0{
  432.             return false;
  433.         }
  434.         if ($res->_received != $res->_transmitted && $severely{
  435.             return false;
  436.         }
  437.         return true;
  438.     /* function checkHost() */
  439.  
  440.     /**
  441.     * Output errors with PHP trigger_error(). You can silence the errors
  442.     * with prefixing a "@" sign to the function call: @Net_Ping::ping(..);
  443.     *
  444.     * @param mixed $error a PEAR error or a string with the error message
  445.     * @return bool false
  446.     * @access private
  447.     * @author Kai Schrder <k.schroeder@php.net>
  448.     */
  449.     function _raiseError($error)
  450.     {
  451.         if (PEAR::isError($error)) {
  452.             $error $error->getMessage();
  453.         }
  454.         trigger_error($errorE_USER_WARNING);
  455.         return false;
  456.     }  /* function _raiseError() */
  457.  
  458.     /**
  459.     * Creates the argument list according to platform differences
  460.     *
  461.     * @return string Argument line
  462.     * @access private
  463.     */
  464.     function _initArgRelation()
  465.     {
  466.         $this->_argRelation["sunos"= array(
  467.                                              "timeout"   => NULL,
  468.                                              "ttl"       => "-t",
  469.                                              "count"     => " ",
  470.                                              "quiet"     => "-q",
  471.                                              "size"      => " ",
  472.                                              "iface"     => "-i"
  473.                                              );
  474.  
  475.         $this->_argRelation["freebsd"= array (
  476.                                                 "timeout"   => "-t",
  477.                                                 "ttl"       => "-m",
  478.                                                 "count"     => "-c",
  479.                                                 "quiet"     => "-q",
  480.                                                 "size"      => NULL,
  481.                                                 "iface"     => NULL
  482.                                                 );
  483.  
  484.         $this->_argRelation["netbsd"= array (
  485.                                                "timeout"   => "-w",
  486.                                                "iface"     => "-I",
  487.                                                "ttl"       => "-T",
  488.                                                "count"     => "-c",
  489.                                                "quiet"     => "-q",
  490.                                                "size"      => "-s"
  491.                                                );
  492.  
  493.         $this->_argRelation["openbsd"= array (
  494.                                                 "timeout"   => "-w",
  495.                                                 "iface"     => "-I",
  496.                                                 "ttl"       => "-t",
  497.                                                 "count"     => "-c",
  498.                                                 "quiet"     => "-q",
  499.                                                 "size"      => "-s"
  500.                                                 );
  501.  
  502.         $this->_argRelation["darwin"= array (
  503.                                                "timeout"   => "-t",
  504.                                                "iface"     => NULL,
  505.                                                "ttl"       => NULL,
  506.                                                "count"     => "-c",
  507.                                                "quiet"     => "-q",
  508.                                                "size"      => NULL
  509.                                                );
  510.  
  511.         $this->_argRelation["linux"= array (
  512.                                               "timeout"   => "-W",
  513.                                               "iface"     => NULL,
  514.                                               "ttl"       => "-t",
  515.                                               "count"     => "-c",
  516.                                               "quiet"     => "-q",
  517.                                               "size"      => "-s",
  518.                                               "deadline"  => "-w"
  519.                                               );
  520.  
  521.         $this->_argRelation["linuxdebian"= array (
  522.                                               "timeout"   => "-W",
  523.                                               "iface"     => NULL,
  524.                                               "ttl"       => "-t",
  525.                                               "count"     => "-c",
  526.                                               "quiet"     => "-q",
  527.                                               "size"      => "-s",
  528.                                               "deadline"  => "-w",
  529.                                               );
  530.  
  531.         $this->_argRelation["linuxredhat8"= array (
  532.                                               "timeout"   => NULL,
  533.                                               "iface"     => "-I",
  534.                                               "ttl"       => "-t",
  535.                                               "count"     => "-c",
  536.                                               "quiet"     => "-q",
  537.                                               "size"      => "-s",
  538.                                               "deadline"  => "-w"
  539.                                               );
  540.  
  541.         $this->_argRelation["linuxredhat9"= array (
  542.                                               "timeout"   => "-W",
  543.                                               "iface"     => "-I",
  544.                                               "ttl"       => "-t",
  545.                                               "count"     => "-c",
  546.                                               "quiet"     => "-q",
  547.                                               "size"      => "-s",
  548.                                               "deadline"  => "-w"
  549.                                               );
  550.  
  551.         $this->_argRelation["windows"= array (
  552.                                                 "timeout"   => "-w",
  553.                                                 "iface"     => NULL,
  554.                                                 "ttl"       => "-i",
  555.                                                 "count"     => "-n",
  556.                                                 "quiet"     => NULL,
  557.                                                 "size"      => "-l"
  558.                                                  );
  559.  
  560.         $this->_argRelation["hpux"= array (
  561.                                              "timeout"   => NULL,
  562.                                              "iface"     => NULL,
  563.                                              "ttl"       => "-t",
  564.                                              "count"     => "-n",
  565.                                              "quiet"     => NULL,
  566.                                              "size"      => " "
  567.                                              );
  568.  
  569.         $this->_argRelation["aix"= array (
  570.                                             "timeout"   => "-i",
  571.                                             "iface"     => NULL,
  572.                                             "ttl"       => "-T",
  573.                                             "count"     => "-c",
  574.                                             "quiet"     => NULL,
  575.                                             "size"      => "-s"
  576.                                             );
  577.     }  /* function _initArgRelation() */
  578. /* class Net_Ping */
  579.  
  580. /**
  581. * Container class for Net_Ping results
  582. *
  583. @author   Jan Lehnardt <jan@php.net>
  584. @version  $Revision: 274728 $
  585. @package  Net
  586. @access   private
  587. */
  588. class Net_Ping_Result
  589. {
  590.     /**
  591.     * ICMP sequence number and associated time in ms
  592.     *
  593.     * @var array 
  594.     * @access private
  595.     */
  596.     var $_icmp_sequence = array()/* array($sequence_number => $time ) */
  597.  
  598.     /**
  599.     * The target's IP Address
  600.     *
  601.     * @var string 
  602.     * @access private
  603.     */
  604.     var $_target_ip;
  605.  
  606.     /**
  607.     * Number of bytes that are sent with each ICMP request
  608.     *
  609.     * @var int 
  610.     * @access private
  611.     */
  612.     var $_bytes_per_request;
  613.  
  614.     /**
  615.     * The total number of bytes that are sent with all ICMP requests
  616.     *
  617.     * @var int 
  618.     * @access private
  619.     */
  620.     var $_bytes_total;
  621.  
  622.     /**
  623.     * The ICMP request's TTL
  624.     *
  625.     * @var int 
  626.     * @access private
  627.     */
  628.     var $_ttl;
  629.  
  630.     /**
  631.     * The raw Net_Ping::result
  632.     *
  633.     * @var array 
  634.     * @access private
  635.     */
  636.     var $_raw_data = array();
  637.  
  638.     /**
  639.     * The Net_Ping::_sysname
  640.     *
  641.     * @var int 
  642.     * @access private
  643.     */
  644.     var $_sysname;
  645.  
  646.     /**
  647.     * Statistical information about the ping
  648.     *
  649.     * @var int 
  650.     * @access private
  651.     */
  652.     var $_round_trip = array()/* array('min' => xxx, 'avg' => yyy, 'max' => zzz) */
  653.  
  654.  
  655.     /**
  656.     * Constructor for the Class
  657.     *
  658.     * @access private
  659.     */
  660.     function Net_Ping_Result($result$sysname)
  661.     {
  662.         $this->_raw_data $result;
  663.  
  664.         // The _sysname property is no longer used by Net_Ping_result.
  665.         // The property remains for backwards compatibility so the
  666.         // getSystemName() method continues to work.
  667.         $this->_sysname  $sysname;
  668.  
  669.         $this->_parseResult();
  670.     /* function Net_Ping_Result() */
  671.  
  672.     /**
  673.     * Factory for Net_Ping_Result
  674.     *
  675.     * @access public
  676.     * @param array $result Net_Ping result
  677.     * @param string $sysname OS_Guess::sysname
  678.     */
  679.     function factory($result$sysname)
  680.     {
  681.         return new Net_Ping_Result($result$sysname);
  682.     }  /* function factory() */
  683.  
  684.     /**
  685.     * Parses the raw output from the ping utility.
  686.     *
  687.     * @access private
  688.     */
  689.     function _parseResult()
  690.     {
  691.         // MAINTAINERS:
  692.         //
  693.         //   If you're in this class fixing or extending the parser
  694.         //   please add another file in the 'tests/test_parser_data/'
  695.         //   directory which exemplafies the problem. And of course
  696.         //   you'll want to run the 'tests/test_parser.php' (which
  697.         //   contains easy how-to instructions) to make sure you haven't
  698.         //   broken any existing behaviour.
  699.  
  700.         // operate on a copy of the raw output since we're going to modify it
  701.         $data $this->_raw_data;
  702.  
  703.         // remove leading and trailing blank lines from output
  704.         $this->_parseResultTrimLines($data);
  705.  
  706.         // separate the output into upper and lower portions,
  707.         // and trim those portions
  708.         $this->_parseResultSeparateParts($data$upper$lower);
  709.         $this->_parseResultTrimLines($upper);
  710.         $this->_parseResultTrimLines($lower);
  711.  
  712.         // extract various things from the ping output . . .
  713.  
  714.         $this->_target_ip         $this->_parseResultDetailTargetIp($upper);
  715.         $this->_bytes_per_request $this->_parseResultDetailBytesPerRequest($upper);
  716.         $this->_ttl               $this->_parseResultDetailTtl($upper);
  717.         $this->_icmp_sequence     $this->_parseResultDetailIcmpSequence($upper);
  718.         $this->_round_trip        $this->_parseResultDetailRoundTrip($lower);
  719.  
  720.         $this->_parseResultDetailTransmitted($lower);
  721.         $this->_parseResultDetailReceived($lower);
  722.         $this->_parseResultDetailLoss($lower);
  723.  
  724.         if isset($this->_transmitted) ) {
  725.             $this->_bytes_total $this->_transmitted $this->_bytes_per_request;
  726.         }
  727.  
  728.     /* function _parseResult() */
  729.  
  730.     /**
  731.      * determinces the number of bytes sent by ping per ICMP ECHO
  732.      *
  733.      * @access private
  734.      */
  735.     function _parseResultDetailBytesPerRequest($upper)
  736.     {
  737.         // The ICMP ECHO REQUEST and REPLY packets should be the same
  738.         // size. So we can also find what we want in the output for any
  739.         // succesful ICMP reply which ping printed.
  740.         for $i=1; $i<count($upper)$i++ {
  741.             // anything like "64 bytes " at the front of any line in $upper??
  742.             if preg_match('/^\s*(\d+)\s*bytes/i'$upper[$i]$matches) ) {
  743.                 return(int)$matches[1);
  744.             }
  745.             // anything like "bytes=64" in any line in the buffer??
  746.             if preg_match('/bytes=(\d+)/i'$upper[$i]$matches) ) {
  747.                 return(int)$matches[1);
  748.             }
  749.         }
  750.  
  751.         // Some flavors of ping give two numbers, as in "n(m) bytes", on
  752.         // the first line. We'll take the first number and add 8 for the
  753.         // 8 bytes of header and such in an ICMP ECHO REQUEST.
  754.         if preg_match('/(\d+)\(\d+\)\D+$/'$upper[0]$matches) ) {
  755.             return(int)(8+$matches[1]) );
  756.         }
  757.  
  758.         // Ok we'll just take the rightmost number on the first line. It
  759.         // could be "bytes of data" or "whole packet size". But to
  760.         // distinguish would require language-specific patterns. Most
  761.         // ping flavors just put the number of data (ie, payload) bytes
  762.         // if they don't specify both numbers as n(m). So we add 8 bytes
  763.         // for the ICMP headers.
  764.         if preg_match('/(\d+)\D+$/'$upper[0]$matches) ) {
  765.             return(int)(8+$matches[1]) );
  766.         }
  767.  
  768.         // then we have no idea...
  769.         returnNULL );
  770.     }
  771.  
  772.     /**
  773.      * determines the round trip time (RTT) in milliseconds for each
  774.      * ICMP ECHO which returned. Note that the array is keyed with the
  775.      * sequence number of each packet; If any packets are lost, the
  776.      * corresponding sequence number will not be found in the array keys.
  777.      *
  778.      * @access private
  779.      */
  780.     function _parseResultDetailIcmpSequence($upper)
  781.     {
  782.         // There is a great deal of variation in the per-packet output
  783.         // from various flavors of ping. There are language variations
  784.         // (time=, rtt=, zeit=, etc), field order variations, and some
  785.         // don't even generate sequence numbers.
  786.         //
  787.         // Since our goal is to build an array listing the round trip
  788.         // times of each packet, our primary concern is to locate the
  789.         // time. The best way seems to be to look for an equals
  790.         // character, a number and then 'ms'. All the "time=" versions
  791.         // of ping will match this methodology, and all the pings which
  792.         // don't show "time=" (that I've seen examples from) also match
  793.         // this methodolgy.
  794.  
  795.         $results = array();
  796.         for $i=1; $i<count($upper)$i++ {
  797.             // by our definition, it's not a success line if we can't
  798.             // find the time
  799.             if preg_match('/=\s*([\d+\.]+)\s*ms/i'$upper[$i]$matches) ) {
  800.                 // float cast deals neatly with values like "126." which
  801.                 // some pings generate
  802.                 $rtt = (float)$matches[1];
  803.                 // does the line have an obvious sequence number?
  804.                 if preg_match('/icmp_seq\s*=\s*([\d+]+)/i'$upper[$i]$matches) ) {
  805.                     $results[$matches[1]] $rtt;
  806.                 }
  807.                 else {
  808.                     // we use the number of the line as the sequence number
  809.                     $results[($i-1)$rtt;
  810.                 }
  811.             }
  812.         }
  813.  
  814.         return$results );
  815.     }
  816.  
  817.     /**
  818.      * Locates the "packets lost" percentage in the ping output
  819.      *
  820.      * @access private
  821.      */
  822.     function _parseResultDetailLoss($lower)
  823.     {
  824.         for $i=1; $i<count($lower)$i++ {
  825.             if preg_match('/(\d+)%/'$lower[$i]$matches) ) {
  826.                 $this->_loss = (int)$matches[1];
  827.                 return;
  828.             }
  829.         }
  830.     }
  831.  
  832.     /**
  833.      * Locates the "packets received" in the ping output
  834.      *
  835.      * @access private
  836.      */
  837.     function _parseResultDetailReceived($lower)
  838.     {
  839.         for $i=1; $i<count($lower)$i++ {
  840.             // the second number on the line
  841.             if preg_match('/^\D*\d+\D+(\d+)/'$lower[$i]$matches) ) {
  842.                 $this->_received = (int)$matches[1];
  843.                 return;
  844.             }
  845.         }
  846.     }
  847.  
  848.     /**
  849.      * determines the mininum, maximum, average and standard deviation
  850.      * of the round trip times.
  851.      *
  852.      * @access private
  853.      */
  854.     function _parseResultDetailRoundTrip($lower)
  855.     {
  856.         // The first pattern will match a sequence of 3 or 4
  857.         // alaphabet-char strings separated with slashes without
  858.         // presuming the order. eg, "min/max/avg" and
  859.         // "min/max/avg/mdev". Some ping flavors don't have the standard
  860.         // deviation value, and some have different names for it when
  861.         // present.
  862.         $p1 '[a-z]+/[a-z]+/[a-z]+/?[a-z]*';
  863.  
  864.         // And the pattern for 3 or 4 numbers (decimal values permitted)
  865.         // separated by slashes.
  866.         $p2 '[0-9\.]+/[0-9\.]+/[0-9\.]+/?[0-9\.]*';
  867.  
  868.         $results = array();
  869.         $matches = array();
  870.         for $i=(count($lower)-1)$i>=0; $i-- {
  871.             if preg_match('|('.$p1.')[^0-9]+('.$p2.')|i'$lower[$i]$matches) ) {
  872.                 break;
  873.             }
  874.         }
  875.  
  876.         // matches?
  877.         if count($matches> 0 {
  878.             // we want standardized keys in the array we return. Here we
  879.             // look for the values (min, max, etc) and setup the return
  880.             // hash
  881.             $fields explode('/'$matches[1]);
  882.             $values explode('/'$matches[2]);
  883.             for $i=0; $i<count($fields)$i++ {
  884.                 if preg_match('/min/i'$fields[$i]) ) {
  885.                     $results['min'= (float)$values[$i];
  886.                 }
  887.                 else if preg_match('/max/i'$fields[$i]) ) {
  888.                     $results['max'= (float)$values[$i];
  889.                 }
  890.                 else if preg_match('/avg/i'$fields[$i]) ) {
  891.                     $results['avg'= (float)$values[$i];
  892.                 }
  893.                 else if preg_match('/dev/i'$fields[$i]) ) # stddev or mdev
  894.                     $results['stddev'= (float)$values[$i];
  895.                 }
  896.             }
  897.             return$results );
  898.         }
  899.  
  900.         // So we had no luck finding RTT info in a/b/c layout. Some ping
  901.         // flavors give the RTT information in an "a=1 b=2 c=3" sort of
  902.         // layout.
  903.         $p3 '[a-z]+\s*=\s*([0-9\.]+).*';
  904.         for $i=(count($lower)-1)$i>=0; $i-- {
  905.             if preg_match('/min.*max/i'$lower[$i]) ) {
  906.                 if preg_match('/'.$p3.$p3.$p3.'/i'$lower[$i]$matches) ) {
  907.                     $results['min'$matches[1];
  908.                     $results['max'$matches[2];
  909.                     $results['avg'$matches[3];
  910.                 }
  911.                 break;
  912.             }
  913.         }
  914.  
  915.         // either an array of min, max and avg from just above, or still
  916.         // the empty array from initialization way above
  917.         return$results );
  918.     }
  919.  
  920.     /**
  921.      * determinces the target IP address actually used by ping
  922.      *
  923.      * @access private
  924.      */
  925.     function _parseResultDetailTargetIp($upper)
  926.     {
  927.         // Grab the first IP addr we can find. Most ping flavors
  928.         // put the target IP on the first line, but some only list it
  929.         // in successful ping packet lines.
  930.         for $i=0; $i<count($upper)$i++ {
  931.             if preg_match('/(\d+\.\d+\.\d+\.\d+)/'$upper[$i]$matches) ) {
  932.                 return$matches[0);
  933.             }
  934.         }
  935.  
  936.         // no idea...
  937.         returnNULL );
  938.     }
  939.  
  940.     /**
  941.      * Locates the "packets received" in the ping output
  942.      *
  943.      * @access private
  944.      */
  945.     function _parseResultDetailTransmitted($lower)
  946.     {
  947.         for $i=1; $i<count($lower)$i++ {
  948.             // the first number on the line
  949.             if preg_match('/^\D*(\d+)/'$lower[$i]$matches) ) {
  950.                 $this->_transmitted = (int)$matches[1];
  951.                 return;
  952.             }
  953.         }
  954.     }
  955.  
  956.     /**
  957.      * determinces the time to live (TTL) actually used by ping
  958.      *
  959.      * @access private
  960.      */
  961.     function _parseResultDetailTtl($upper)
  962.     {
  963.         //extract TTL from first icmp echo line
  964.         for $i=1; $i<count($upper)$i++ {
  965.             if (   preg_match('/ttl=(\d+)/i'$upper[$i]$matches)
  966.                 && (int)$matches[1> 0
  967.                 {
  968.                 return(int)$matches[1);
  969.             }
  970.         }
  971.  
  972.         // No idea what ttl was used. Probably because no packets
  973.         // received in reply.
  974.         returnNULL );
  975.     }
  976.  
  977.     /**
  978.     * Modifies the array to temoves leading and trailing blank lines
  979.     *
  980.     * @access private
  981.     */
  982.     function _parseResultTrimLines(&$data)
  983.     {
  984. if !is_array($data) ) {
  985. print_r($this);
  986. exit;
  987. }
  988.         // Trim empty elements from the front
  989.         while preg_match('/^\s*$/'$data[0]) ) {
  990.             array_splice($data01);
  991.         }
  992.         // Trim empty elements from the back
  993.         while preg_match('/^\s*$/'$data[(count($data)-1)]) ) {
  994.             array_splice($data-11);
  995.         }
  996.     }
  997.  
  998.     /**
  999.     * Separates the upper portion (data about individual ICMP ECHO
  1000.     * packets) and the lower portion (statistics about the ping
  1001.     * execution as a whole.)
  1002.     *
  1003.     * @access private
  1004.     */
  1005.     function _parseResultSeparateParts($data&$upper&$lower)
  1006.     {
  1007.         $upper = array();
  1008.         $lower = array();
  1009.  
  1010.         // find the blank line closest to the end
  1011.         $dividerIndex count($data- 1;
  1012.         while !preg_match('/^\s*$/'$data[$dividerIndex]) ) {
  1013.             $dividerIndex--;
  1014.             if $dividerIndex < 0 {
  1015.                 break;
  1016.             }
  1017.         }
  1018.  
  1019.         // This is horrible; All the other methods assume we're able to
  1020.         // separate the upper (preamble and per-packet output) and lower
  1021.         // (statistics and summary output) sections.
  1022.         if $dividerIndex < 0 {
  1023.             $upper $data;
  1024.             $lower $data;
  1025.             return;
  1026.         }
  1027.  
  1028.         for $i=0; $i<$dividerIndex$i++ {
  1029.             $upper[$data[$i];
  1030.         }
  1031.         for $i=(1+$dividerIndex)$i<count($data)$i++ {
  1032.             $lower[$data[$i];
  1033.         }
  1034.     }
  1035.  
  1036.     /**
  1037.     * Returns a Ping_Result property
  1038.     *
  1039.     * @param string $name property name
  1040.     * @return mixed property value
  1041.     * @access public
  1042.     */
  1043.     function getValue($name)
  1044.     {
  1045.         return isset($this->$name)?$this->$name:'';
  1046.     /* function getValue() */
  1047.  
  1048.     /**
  1049.     * Accessor for $this->_target_ip;
  1050.     *
  1051.     * @return string IP address
  1052.     * @access public
  1053.     * @see Ping_Result::_target_ip
  1054.     */
  1055.     function getTargetIp()
  1056.     {
  1057.         return $this->_target_ip;
  1058.     /* function getTargetIp() */
  1059.  
  1060.     /**
  1061.     * Accessor for $this->_icmp_sequence;
  1062.     *
  1063.     * @return array ICMP sequence
  1064.     * @access private
  1065.     * @see Ping_Result::_icmp_sequence
  1066.     */
  1067.     function getICMPSequence()
  1068.     {
  1069.         return $this->_icmp_sequence;
  1070.     /* function getICMPSequencs() */
  1071.  
  1072.     /**
  1073.     * Accessor for $this->_bytes_per_request;
  1074.     *
  1075.     * @return int bytes per request
  1076.     * @access private
  1077.     * @see Ping_Result::_bytes_per_request
  1078.     */
  1079.     function getBytesPerRequest()
  1080.     {
  1081.         return $this->_bytes_per_request;
  1082.     /* function getBytesPerRequest() */
  1083.  
  1084.     /**
  1085.     * Accessor for $this->_bytes_total;
  1086.     *
  1087.     * @return int total bytes
  1088.     * @access private
  1089.     * @see Ping_Result::_bytes_total
  1090.     */
  1091.     function getBytesTotal()
  1092.     {
  1093.         return $this->_bytes_total;
  1094.     /* function getBytesTotal() */
  1095.  
  1096.     /**
  1097.     * Accessor for $this->_ttl;
  1098.     *
  1099.     * @return int TTL
  1100.     * @access private
  1101.     * @see Ping_Result::_ttl
  1102.     */
  1103.     function getTTL()
  1104.     {
  1105.         return $this->_ttl;
  1106.     /* function getTTL() */
  1107.  
  1108.     /**
  1109.     * Accessor for $this->_raw_data;
  1110.     *
  1111.     * @return array raw data
  1112.     * @access private
  1113.     * @see Ping_Result::_raw_data
  1114.     */
  1115.     function getRawData()
  1116.     {
  1117.         return $this->_raw_data;
  1118.     /* function getRawData() */
  1119.  
  1120.     /**
  1121.     * Accessor for $this->_sysname;
  1122.     *
  1123.     * @return string OS_Guess::sysname
  1124.     * @access private
  1125.     * @see Ping_Result::_sysname
  1126.     */
  1127.     function getSystemName()
  1128.     {
  1129.         return $this->_sysname;
  1130.     /* function getSystemName() */
  1131.  
  1132.     /**
  1133.     * Accessor for $this->_round_trip;
  1134.     *
  1135.     * @return array statistical information
  1136.     * @access private
  1137.     * @see Ping_Result::_round_trip
  1138.     */
  1139.     function getRoundTrip()
  1140.     {
  1141.         return $this->_round_trip;
  1142.     /* function getRoundTrip() */
  1143.  
  1144.     /**
  1145.     * Accessor for $this->_round_trip['min'];
  1146.     *
  1147.     * @return array statistical information
  1148.     * @access private
  1149.     * @see Ping_Result::_round_trip
  1150.     */
  1151.     function getMin()
  1152.     {
  1153.         return $this->_round_trip['min'];
  1154.     /* function getMin() */
  1155.  
  1156.     /**
  1157.     * Accessor for $this->_round_trip['max'];
  1158.     *
  1159.     * @return array statistical information
  1160.     * @access private
  1161.     * @see Ping_Result::_round_trip
  1162.     */
  1163.     function getMax()
  1164.     {
  1165.         return $this->_round_trip['max'];
  1166.     /* function getMax() */
  1167.  
  1168.     /**
  1169.     * Accessor for $this->_round_trip['stddev'];
  1170.     *
  1171.     * @return array statistical information
  1172.     * @access private
  1173.     * @see Ping_Result::_round_trip
  1174.     */
  1175.     function getStddev()
  1176.     {
  1177.         return $this->_round_trip['stddev'];
  1178.     /* function getStddev() */
  1179.  
  1180.     /**
  1181.     * Accessor for $this->_round_tripp['avg'];
  1182.     *
  1183.     * @return array statistical information
  1184.     * @access private
  1185.     * @see Ping_Result::_round_trip
  1186.     */
  1187.     function getAvg()
  1188.     {
  1189.         return $this->_round_trip['avg'];
  1190.     /* function getAvg() */
  1191.  
  1192.     /**
  1193.     * Accessor for $this->_transmitted;
  1194.     *
  1195.     * @return array statistical information
  1196.     * @access private
  1197.     */
  1198.     function getTransmitted()
  1199.     {
  1200.         return $this->_transmitted;
  1201.     /* function getTransmitted() */
  1202.  
  1203.     /**
  1204.     * Accessor for $this->_received;
  1205.     *
  1206.     * @return array statistical information
  1207.     * @access private
  1208.     */
  1209.     function getReceived()
  1210.     {
  1211.         return $this->_received;
  1212.     /* function getReceived() */
  1213.  
  1214.     /**
  1215.     * Accessor for $this->_loss;
  1216.     *
  1217.     * @return array statistical information
  1218.     * @access private
  1219.     */
  1220.     function getLoss()
  1221.     {
  1222.         return $this->_loss;
  1223.     /* function getLoss() */
  1224.  
  1225. /* class Net_Ping_Result */
  1226. ?>

Documentation generated on Mon, 11 Mar 2019 15:35:13 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.