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

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