Source for file Ping.php
Documentation is available at Ping.php 
// +----------------------------------------------------------------------+  
// +----------------------------------------------------------------------+  
// | Copyright (c) 1997-2004 The PHP Group                                |  
// +----------------------------------------------------------------------+  
// | This source file is subject to version 2.0 of the PHP license,       |  
// | that is bundled with this package in the file LICENSE, and is        |  
// | available at through the world-wide-web at                           |  
// | http://www.php.net/license/2_02.txt.                                 |  
// | If you did not receive a copy of the PHP license and are unable to   |  
// | obtain it through the world-wide-web, please send a note to          |  
// | license@php.net so we can mail you a copy immediately.               |  
// +----------------------------------------------------------------------+  
// | Authors: Martin Jansen <mj@php.net>                                  |  
// |          Tomas V.V.Cox <cox@idecnet.com>                             |  
// |          Jan Lehnardt  <jan@php.net>                                 |  
// |          Kai Schrder <k.schroeder@php.net>                          |  
// |          Craig Constantine <cconstantine@php.net>                    |  
// +----------------------------------------------------------------------+  
// $Id: Ping.php 274728 2009-01-27 20:14:00Z cconstantine $  
require_once "OS/Guess.php";   
define('NET_PING_FAILED_MSG',                     'execution of ping failed'        );   
define('NET_PING_HOST_NOT_FOUND_MSG',             'unknown host'                    );   
define('NET_PING_INVALID_ARGUMENTS_MSG',          'invalid argument array'          );   
define('NET_PING_CANT_LOCATE_PING_BINARY_MSG',    'unable to locate the ping binary');   
define('NET_PING_RESULT_UNSUPPORTED_BACKEND_MSG', 'Backend not Supported'           );   
define('NET_PING_HOST_NOT_FOUND',             1 );   
define('NET_PING_INVALID_ARGUMENTS',          2 );   
define('NET_PING_CANT_LOCATE_PING_BINARY',    3 );   
define('NET_PING_RESULT_UNSUPPORTED_BACKEND', 4 );   
* Wrapper class for ping calls  
*   require_once "Net/Ping.php";  
*   $ping = Net_Ping::factory();  
*   if(PEAR::isError($ping)) {  
*     echo $ping->getMessage();  
*     $ping->setArgs(array('count' => 2));  
*     var_dump($ping->ping('example.com'));  
* @author   Jan Lehnardt <jan@php.net>  
* @version  $Revision: 274728 $  
    * Location where the ping program is stored  
    * Array with the result from the ping execution  
    * OS_Guess->getSysname result  
    * Indicates if an empty array was given to setArgs  
    * Contains the argument->option relation  
    var $_argRelation = array ();   
    * Constructor for the Class  
    function Net_Ping ($ping_path, $sysname)  
        $this->_ping_path =  $ping_path;   
        $this->_sysname   =  $sysname;   
        $this->_initArgRelation ();   
    } /* function Net_Ping() */  
            return new  Net_Ping($ping_path, $sysname);   
    } /* function factory() */  
     * Resolve the system name  
    function _setSystemName ()  
        $OS_Guess  = new OS_Guess;   
        $sysname   =  $OS_Guess->getSysname ();   
        // Refine the sysname for different Linux bundles/vendors. (This  
        // should go away if OS_Guess was ever extended to give vendor  
        // and vendor-version guesses.)  
        // Bear in mind that $sysname is eventually used to craft a  
        // method name to figure out which backend gets used to parse  
        // the ping output. Elsewhere, we'll set $sysname back before  
        if ('linux' ==  $sysname) {  
                $sysname =  'linuxredhat9';   
                $sysname =  'linuxdebian';   
                    $sysname =  'linuxredhat8';   
                    $sysname =  'linuxredhat9';   
    } /* function _setSystemName */  
    * Set the arguments array  
    * @param array $args Hash with options  
    * @return mixed true or PEAR_error  
        $this->_setNoArgs ($args);   
    } /* function setArgs() */  
    * @param array $args Hash with options  
    function _setNoArgs ($args)  
    } /* function _setNoArgs() */  
    * Sets the system's path to the ping binary  
    function _setPingPath ($sysname)  
        if ("windows" ==  $sysname) {  
            $ping_path =  exec("which ping", $output, $status);   
                // be certain "which" did what we expect. (ref bug #12791)  
    } /* function _setPingPath() */  
    * Creates the argument list according to platform differences  
    * @return string Argument line  
    function _createArgList ()  
        foreach($this->_args AS  $option =>  $value) {  
            if(!empty ($option) && isset ($this->_argRelation[$this->_sysname][$option]) && NULL !=  $this->_argRelation[$this->_sysname][$option]) {  
                $ {$option} =  $this->_argRelation[$this->_sysname][$option]. " ". $value. " ";  
        switch($this->_sysname) {  
             if ($size ||  $count ||  $iface) {  
                 /* $size and $count must be _both_ defined */  
             $retval['pre'] =  $iface. $seq. $ttl;   
             $retval['post'] =  $size. $count;   
             $retval['pre'] =  $quiet. $count. $ttl. $timeout;   
             $retval['pre'] =  $count. $timeout. $size;   
             $retval['pre'] =  $quiet. $count. $iface. $size. $ttl. $timeout;   
             $retval['pre'] =  $quiet. $count. $iface. $size. $ttl. $timeout;   
             $retval['pre'] =  $quiet. $deadline. $count. $ttl. $size. $timeout;   
             $retval['pre'] =  $quiet. $count. $ttl. $size. $timeout;   
             $this->_sysname =  'linux';  // undo linux vendor refinement hack  
             $retval['pre'] =  $iface. $ttl. $count. $quiet. $size. $deadline;   
             $this->_sysname =  'linux';  // undo linux vendor refinement hack  
             $retval['pre'] =  $timeout. $iface. $ttl. $count. $quiet. $size. $deadline;   
             $this->_sysname =  'linux';  // undo linux vendor refinement hack  
             $retval['pre'] =  $count. $ttl. $timeout;   
             $retval['post'] =  $size. $count;   
            $retval['pre'] =  $count. $timeout. $ttl. $size;   
    }  /* function _createArgList() */  
    * @param  string    $host   hostname  
    * @return mixed  String on error or array with the result  
            $this->setArgs(array ('count' => 3 ));   
        $argList =  $this->_createArgList ();   
        $cmd =  $this->_ping_path. " ". $argList['pre']. " ". escapeshellcmd($host). " ". $argList['post'];   
        // since we return a new instance of Net_Ping_Result (on  
        // success), users may call the ping() method repeatedly to  
        // perform unrelated ping tests Make sure we don't have raw data  
        // from a previous call laying in the _result array.  
        $this->_result = array ();   
        exec($cmd, $this->_result);   
        if (count($this->_result) == 0 ) {  
            // Here we pass $this->_sysname to the factory(), but it is  
            // not actually used by the class. It's only maintained in  
            // the Net_Ping_Result class because the  
            // Net_Ping_Result::getSysName() method needs to be retained  
            // for backwards compatibility.  
            return Net_Ping_Result ::factory ($this->_result, $this->_sysname);   
    * Check if a host is up by pinging it  
    * @param string $host   The host to test  
    * @param bool $severely If some of the packages did reach the host  
    *                        and severely is false the function will return true  
    * @return bool True on success or false otherwise  
        $this->setArgs(array ("count" => 10 ,  
        $res =  $this->ping($host);   
        if (PEAR ::isError ($res)) {  
        if ($res->_received == 0 ) {  
        if ($res->_received !=  $res->_transmitted &&  $severely) {  
    } /* function checkHost() */  
    * Output errors with PHP trigger_error(). You can silence the errors  
    * with prefixing a "@" sign to the function call: @Net_Ping::ping(..);  
    * @param mixed $error a PEAR error or a string with the error message  
    * @author Kai Schrder <k.schroeder@php.net>  
    function _raiseError ($error)  
        if (PEAR ::isError ($error)) {  
            $error =  $error->getMessage ();   
    }  /* function _raiseError() */  
    * Creates the argument list according to platform differences  
    * @return string Argument line  
    function _initArgRelation ()  
        $this->_argRelation["sunos"] = array (  
        $this->_argRelation["freebsd"] = array  (  
        $this->_argRelation["netbsd"] = array  (  
        $this->_argRelation["openbsd"] = array  (  
        $this->_argRelation["darwin"] = array  (  
        $this->_argRelation["linux"] = array  (  
        $this->_argRelation["linuxdebian"] = array  (  
        $this->_argRelation["linuxredhat8"] = array  (  
        $this->_argRelation["linuxredhat9"] = array  (  
        $this->_argRelation["windows"] = array  (  
        $this->_argRelation["hpux"] = array  (  
        $this->_argRelation["aix"] = array  (  
    }  /* function _initArgRelation() */  
* Container class for Net_Ping results  
* @author   Jan Lehnardt <jan@php.net>  
* @version  $Revision: 274728 $  
    * ICMP sequence number and associated time in ms  
    var $_icmp_sequence = array ();  /* array($sequence_number => $time ) */  
    * The target's IP Address  
    * Number of bytes that are sent with each ICMP request  
    * The total number of bytes that are sent with all ICMP requests  
    * The raw Net_Ping::result  
    var $_raw_data = array ();   
    * Statistical information about the ping  
    var $_round_trip = array ();  /* array('min' => xxx, 'avg' => yyy, 'max' => zzz) */  
    * Constructor for the Class  
    function Net_Ping_Result ($result, $sysname)  
        $this->_raw_data =  $result;   
        // The _sysname property is no longer used by Net_Ping_result.  
        // The property remains for backwards compatibility so the  
        // getSystemName() method continues to work.  
        $this->_sysname  =  $sysname;   
    } /* function Net_Ping_Result() */  
    * Factory for Net_Ping_Result  
    * @param array $result Net_Ping result  
    * @param string $sysname OS_Guess::sysname  
    function factory ($result, $sysname)  
        return new Net_Ping_Result ($result, $sysname);   
    }  /* function factory() */  
    * Parses the raw output from the ping utility.  
        //   If you're in this class fixing or extending the parser  
        //   please add another file in the 'tests/test_parser_data/'  
        //   directory which exemplafies the problem. And of course  
        //   you'll want to run the 'tests/test_parser.php' (which  
        //   contains easy how-to instructions) to make sure you haven't  
        //   broken any existing behaviour.  
        // operate on a copy of the raw output since we're going to modify it  
        $data =  $this->_raw_data;   
        // remove leading and trailing blank lines from output  
        $this->_parseResultTrimLines ($data);   
        // separate the output into upper and lower portions,  
        // and trim those portions  
        $this->_parseResultSeparateParts ($data, $upper, $lower);   
        $this->_parseResultTrimLines ($upper);   
        $this->_parseResultTrimLines ($lower);   
        // extract various things from the ping output . . .  
        $this->_target_ip         =  $this->_parseResultDetailTargetIp ($upper);   
        $this->_bytes_per_request =  $this->_parseResultDetailBytesPerRequest ($upper);   
        $this->_ttl               =  $this->_parseResultDetailTtl ($upper);   
        $this->_icmp_sequence     =  $this->_parseResultDetailIcmpSequence ($upper);   
        $this->_round_trip        =  $this->_parseResultDetailRoundTrip ($lower);   
        $this->_parseResultDetailTransmitted ($lower);   
        $this->_parseResultDetailReceived ($lower);   
        $this->_parseResultDetailLoss ($lower);   
        if ( isset ($this->_transmitted) ) {  
            $this->_bytes_total =  $this->_transmitted *  $this->_bytes_per_request;   
    } /* function _parseResult() */  
     * determinces the number of bytes sent by ping per ICMP ECHO  
    function _parseResultDetailBytesPerRequest ($upper)  
        // The ICMP ECHO REQUEST and REPLY packets should be the same  
        // size. So we can also find what we want in the output for any  
        // succesful ICMP reply which ping printed.  
        for ( $i=1;  $i< count($upper);  $i++  ) {  
            // anything like "64 bytes " at the front of any line in $upper??  
            if ( preg_match('/^\s*(\d+)\s*bytes/i', $upper[$i], $matches) ) {  
                return( (int) $matches[1 ] );   
            // anything like "bytes=64" in any line in the buffer??  
            if ( preg_match('/bytes=(\d+)/i', $upper[$i], $matches) ) {  
                return( (int) $matches[1 ] );   
        // Some flavors of ping give two numbers, as in "n(m) bytes", on  
        // the first line. We'll take the first number and add 8 for the  
        // 8 bytes of header and such in an ICMP ECHO REQUEST.  
        if ( preg_match('/(\d+)\(\d+\)\D+$/', $upper[0 ], $matches) ) {  
            return( (int) (8+ $matches[1 ]) );   
        // Ok we'll just take the rightmost number on the first line. It  
        // could be "bytes of data" or "whole packet size". But to  
        // distinguish would require language-specific patterns. Most  
        // ping flavors just put the number of data (ie, payload) bytes  
        // if they don't specify both numbers as n(m). So we add 8 bytes  
        if ( preg_match('/(\d+)\D+$/', $upper[0 ], $matches) ) {  
            return( (int) (8+ $matches[1 ]) );   
        // then we have no idea...  
     * determines the round trip time (RTT) in milliseconds for each  
     * ICMP ECHO which returned. Note that the array is keyed with the  
     * sequence number of each packet; If any packets are lost, the  
     * corresponding sequence number will not be found in the array keys.  
    function _parseResultDetailIcmpSequence ($upper)  
        // There is a great deal of variation in the per-packet output  
        // from various flavors of ping. There are language variations  
        // (time=, rtt=, zeit=, etc), field order variations, and some  
        // don't even generate sequence numbers.  
        // Since our goal is to build an array listing the round trip  
        // times of each packet, our primary concern is to locate the  
        // time. The best way seems to be to look for an equals  
        // character, a number and then 'ms'. All the "time=" versions  
        // of ping will match this methodology, and all the pings which  
        // don't show "time=" (that I've seen examples from) also match  
        for ( $i=1;  $i< count($upper);  $i++  ) {  
            // by our definition, it's not a success line if we can't  
            if ( preg_match('/=\s*([\d+\.]+)\s*ms/i', $upper[$i], $matches) ) {  
                // float cast deals neatly with values like "126." which  
                $rtt = (float) $matches[1 ];   
                // does the line have an obvious sequence number?  
                if ( preg_match('/icmp_seq\s*=\s*([\d+]+)/i', $upper[$i], $matches) ) {  
                    $results[$matches[1 ]] =  $rtt;   
                    // we use the number of the line as the sequence number  
     * Locates the "packets lost" percentage in the ping output  
    function _parseResultDetailLoss ($lower)  
        for ( $i=1;  $i< count($lower);  $i++  ) {  
            if ( preg_match('/(\d+)%/', $lower[$i], $matches) ) {  
                $this->_loss = (int) $matches[1 ];   
     * Locates the "packets received" in the ping output  
    function _parseResultDetailReceived ($lower)  
        for ( $i=1;  $i< count($lower);  $i++  ) {  
            // the second number on the line  
            if ( preg_match('/^\D*\d+\D+(\d+)/', $lower[$i], $matches) ) {  
                $this->_received = (int) $matches[1 ];   
     * determines the mininum, maximum, average and standard deviation  
     * of the round trip times.  
    function _parseResultDetailRoundTrip ($lower)  
        // The first pattern will match a sequence of 3 or 4  
        // alaphabet-char strings separated with slashes without  
        // presuming the order. eg, "min/max/avg" and  
        // "min/max/avg/mdev". Some ping flavors don't have the standard  
        // deviation value, and some have different names for it when  
        $p1 =  '[a-z]+/[a-z]+/[a-z]+/?[a-z]*';   
        // And the pattern for 3 or 4 numbers (decimal values permitted)  
        $p2 =  '[0-9\.]+/[0-9\.]+/[0-9\.]+/?[0-9\.]*';   
        for ( $i= (count($lower)-1 );  $i>=0;  $i--  ) {  
            if ( preg_match('|('. $p1. ')[^0-9]+('. $p2. ')|i', $lower[$i], $matches) ) {  
        if ( count($matches) > 0  ) {  
            // we want standardized keys in the array we return. Here we  
            // look for the values (min, max, etc) and setup the return  
            $fields =  explode('/', $matches[1 ]);   
            $values =  explode('/', $matches[2 ]);   
            for ( $i=0;  $i< count($fields);  $i++  ) {  
                    $results['min'] = (float) $values[$i];   
                    $results['max'] = (float) $values[$i];   
                    $results['avg'] = (float) $values[$i];   
                else  if ( preg_match('/dev/i', $fields[$i]) ) { # stddev or mdev 
                    $results['stddev'] = (float) $values[$i];   
        // So we had no luck finding RTT info in a/b/c layout. Some ping  
        // flavors give the RTT information in an "a=1 b=2 c=3" sort of  
        $p3 =  '[a-z]+\s*=\s*([0-9\.]+).*';   
        for ( $i= (count($lower)-1 );  $i>=0;  $i--  ) {  
                if ( preg_match('/'. $p3. $p3. $p3. '/i', $lower[$i], $matches) ) {  
                    $results['min'] =  $matches[1 ];   
                    $results['max'] =  $matches[2 ];   
                    $results['avg'] =  $matches[3 ];   
        // either an array of min, max and avg from just above, or still  
        // the empty array from initialization way above  
     * determinces the target IP address actually used by ping  
    function _parseResultDetailTargetIp ($upper)  
        // Grab the first IP addr we can find. Most ping flavors  
        // put the target IP on the first line, but some only list it  
        // in successful ping packet lines.  
        for ( $i=0;  $i< count($upper);  $i++  ) {  
            if ( preg_match('/(\d+\.\d+\.\d+\.\d+)/', $upper[$i], $matches) ) {  
     * Locates the "packets received" in the ping output  
    function _parseResultDetailTransmitted ($lower)  
        for ( $i=1;  $i< count($lower);  $i++  ) {  
            // the first number on the line  
            if ( preg_match('/^\D*(\d+)/', $lower[$i], $matches) ) {  
                $this->_transmitted = (int) $matches[1 ];   
     * determinces the time to live (TTL) actually used by ping  
    function _parseResultDetailTtl ($upper)  
        //extract TTL from first icmp echo line  
        for ( $i=1;  $i< count($upper);  $i++  ) {  
            if (   preg_match('/ttl=(\d+)/i', $upper[$i], $matches)  
                return( (int) $matches[1 ] );   
        // No idea what ttl was used. Probably because no packets  
    * Modifies the array to temoves leading and trailing blank lines  
    function _parseResultTrimLines (&$data)  
        // Trim empty elements from the front  
        // Trim empty elements from the back  
    * Separates the upper portion (data about individual ICMP ECHO  
    * packets) and the lower portion (statistics about the ping  
    function _parseResultSeparateParts ($data, &$upper, &$lower)  
        // find the blank line closest to the end  
        $dividerIndex =  count($data) - 1;   
        while  ( !preg_match('/^\s*$/', $data[$dividerIndex]) ) { 
            if ( $dividerIndex < 0  ) {  
        // This is horrible; All the other methods assume we're able to  
        // separate the upper (preamble and per-packet output) and lower  
        // (statistics and summary output) sections.  
        if ( $dividerIndex < 0  ) {  
        for ( $i=0;  $i< $dividerIndex;  $i++  ) {  
        for ( $i= (1+ $dividerIndex);  $i< count($data);  $i++  ) {  
    * Returns a Ping_Result property  
    * @param string $name property name  
    * @return mixed property value  
        return isset ($this->$name)? $this->$name: '';   
    } /* function getValue() */  
    * Accessor for $this->_target_ip;  
    * @return string IP address  
    * @see Ping_Result::_target_ip  
        return $this->_target_ip;   
    } /* function getTargetIp() */  
    * Accessor for $this->_icmp_sequence;  
    * @return array ICMP sequence  
    * @see Ping_Result::_icmp_sequence  
    function getICMPSequence ()  
        return $this->_icmp_sequence;   
    } /* function getICMPSequencs() */  
    * Accessor for $this->_bytes_per_request;  
    * @return int bytes per request  
    * @see Ping_Result::_bytes_per_request  
    function getBytesPerRequest ()  
        return $this->_bytes_per_request;   
    } /* function getBytesPerRequest() */  
    * Accessor for $this->_bytes_total;  
    * @return int total bytes  
    * @see Ping_Result::_bytes_total  
        return $this->_bytes_total;   
    } /* function getBytesTotal() */  
    * Accessor for $this->_ttl;  
    } /* function getTTL() */  
    * Accessor for $this->_raw_data;  
    * @see Ping_Result::_raw_data  
    } /* function getRawData() */  
    * Accessor for $this->_sysname;  
    * @return string OS_Guess::sysname  
    * @see Ping_Result::_sysname  
    } /* function getSystemName() */  
    * Accessor for $this->_round_trip;  
    * @return array statistical information  
    * @see Ping_Result::_round_trip  
        return $this->_round_trip;   
    } /* function getRoundTrip() */  
    * Accessor for $this->_round_trip['min'];  
    * @return array statistical information  
    * @see Ping_Result::_round_trip  
        return $this->_round_trip['min'];   
    } /* function getMin() */  
    * Accessor for $this->_round_trip['max'];  
    * @return array statistical information  
    * @see Ping_Result::_round_trip  
        return $this->_round_trip['max'];   
    } /* function getMax() */  
    * Accessor for $this->_round_trip['stddev'];  
    * @return array statistical information  
    * @see Ping_Result::_round_trip  
        return $this->_round_trip['stddev'];   
    } /* function getStddev() */  
    * Accessor for $this->_round_tripp['avg'];  
    * @return array statistical information  
    * @see Ping_Result::_round_trip  
        return $this->_round_trip['avg'];   
    } /* function getAvg() */  
    * Accessor for $this->_transmitted;  
    * @return array statistical information  
    function getTransmitted ()  
        return $this->_transmitted;   
    } /* function getTransmitted() */  
    * Accessor for $this->_received;  
    * @return array statistical information  
    } /* function getReceived() */  
    * Accessor for $this->_loss;  
    * @return array statistical information  
    } /* function getLoss() */  
} /* class Net_Ping_Result */  
 
 
        
		    
 
		    Documentation generated on Mon, 11 Mar 2019 15:35:13 -0400 by  phpDocumentor 1.4.4. PEAR Logo Copyright ©  PHP Group 2004.
	        
       |