Simple Groupware PHP Cross Reference Groupware Applications

Source: /src/lib/pear/Socket.php - 588 lines - 17878 bytes - Summary - Text - Print

   1  <?php
   2  //
   3  // +----------------------------------------------------------------------+
   4  // | PHP Version 4                                                        |
   5  // +----------------------------------------------------------------------+
   6  // | Copyright (c) 1997-2003 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: Stig Bakken <ssb@php.net>                                   |
  17  // |          Chuck Hagenbuch <chuck@horde.org>                           |
  18  // +----------------------------------------------------------------------+
  19  //
  20  // $Id: Socket.php,v 1.38 2008/02/15 18:24:17 chagenbu Exp $
  21  
  22  define('NET_SOCKET_READ',  1);
  23  define('NET_SOCKET_WRITE', 2);
  24  define('NET_SOCKET_ERROR', 4);
  25  
  26  /**
  27   * Generalized Socket class.
  28   *
  29   * @version 1.1
  30   * @author Stig Bakken <ssb@php.net>
  31   * @author Chuck Hagenbuch <chuck@horde.org>
  32   */
  33  class Net_Socket extends PEAR {
  34  
  35      /**
  36       * Socket file pointer.
  37       * @var resource $fp
  38       */
  39      var $fp = null;
  40  
  41      /**
  42       * Whether the socket is blocking. Defaults to true.
  43       * @var boolean $blocking
  44       */
  45      var $blocking = true;
  46  
  47      /**
  48       * Whether the socket is persistent. Defaults to false.
  49       * @var boolean $persistent
  50       */
  51      var $persistent = false;
  52  
  53      /**
  54       * The IP address to connect to.
  55       * @var string $addr
  56       */
  57      var $addr = '';
  58  
  59      /**
  60       * The port number to connect to.
  61       * @var integer $port
  62       */
  63      var $port = 0;
  64  
  65      /**
  66       * Number of seconds to wait on socket connections before assuming
  67       * there's no more data. Defaults to no timeout.
  68       * @var integer $timeout
  69       */
  70      var $timeout = false;
  71  
  72      /**
  73       * Number of bytes to read at a time in readLine() and
  74       * readAll(). Defaults to 2048.
  75       * @var integer $lineLength
  76       */
  77      var $lineLength = 2048;
  78  
  79      /**
  80       * Connect to the specified port. If called when the socket is
  81       * already connected, it disconnects and connects again.
  82       *
  83       * @param string  $addr        IP address or host name.
  84       * @param integer $port        TCP port number.
  85       * @param boolean $persistent  (optional) Whether the connection is
  86       *                             persistent (kept open between requests
  87       *                             by the web server).
  88       * @param integer $timeout     (optional) How long to wait for data.
  89       * @param array   $options     See options for stream_context_create.
  90       *
  91       * @access public
  92       *
  93       * @return boolean | PEAR_Error  True on success or a PEAR_Error on failure.
  94       */
  95      function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null)
  96      {
  97          if (is_resource($this->fp)) {
  98              @fclose($this->fp);
  99              $this->fp = null;
 100          }
 101  
 102          if (!$addr) {
 103              return $this->raiseError('$addr cannot be empty');
 104          } elseif (strspn($addr, '.0123456789') == strlen($addr) ||
 105                    strstr($addr, '/') !== false) {
 106              $this->addr = $addr;
 107          } else {
 108              $this->addr = @gethostbyname($addr);
 109          }
 110  
 111          $this->port = $port % 65536;
 112  
 113          if ($persistent !== null) {
 114              $this->persistent = $persistent;
 115          }
 116  
 117          if ($timeout !== null) {
 118              $this->timeout = $timeout;
 119          }
 120  
 121          $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
 122          $errno = 0;
 123          $errstr = '';
 124          if ($options && function_exists('stream_context_create')) {
 125              if ($this->timeout) {
 126                  $timeout = $this->timeout;
 127              } else {
 128                  $timeout = 0;
 129              }
 130              $context = stream_context_create($options);
 131  
 132              // Since PHP 5 fsockopen doesn't allow context specification
 133              if (function_exists('stream_socket_client')) {
 134                  $flags = $this->persistent ? STREAM_CLIENT_PERSISTENT : STREAM_CLIENT_CONNECT;
 135                  $addr = $this->addr . ':' . $this->port;
 136                  $fp = stream_socket_client($addr, $errno, $errstr, $timeout, $flags, $context);
 137              } else {
 138              $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
 139              }
 140          } else {
 141              ob_start();
 142              if ($this->timeout) {
 143                  $fp = $openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
 144              } else {
 145                  $fp = $openfunc($this->addr, $this->port, $errno, $errstr);
 146              }
 147              $php_errormsg = ob_get_contents();
 148              ob_end_clean();
 149          }
 150  
 151          if (!$fp) {
 152              if ($errno == 0 && isset($php_errormsg)) {
 153                  $errstr = $php_errormsg;
 154              }
 155              return $this->raiseError($errstr, $errno);
 156          }
 157          $this->fp = $fp;
 158          return $this->setBlocking($this->blocking);
 159      }
 160  
 161      /**
 162       * Disconnects from the peer, closes the socket.
 163       *
 164       * @access public
 165       * @return mixed true on success or a PEAR_Error instance otherwise
 166       */
 167      function disconnect()
 168      {
 169          if (!is_resource($this->fp)) {
 170              return $this->raiseError('not connected');
 171          }
 172  
 173          @fclose($this->fp);
 174          $this->fp = null;
 175          return true;
 176      }
 177  
 178      /**
 179       * Find out if the socket is in blocking mode.
 180       *
 181       * @access public
 182       * @return boolean  The current blocking mode.
 183       */
 184      function isBlocking()
 185      {
 186          return $this->blocking;
 187      }
 188  
 189      /**
 190       * Sets whether the socket connection should be blocking or
 191       * not. A read call to a non-blocking socket will return immediately
 192       * if there is no data available, whereas it will block until there
 193       * is data for blocking sockets.
 194       *
 195       * @param boolean $mode  True for blocking sockets, false for nonblocking.
 196       * @access public
 197       * @return mixed true on success or a PEAR_Error instance otherwise
 198       */
 199      function setBlocking($mode)
 200      {
 201          if (!is_resource($this->fp)) {
 202              return $this->raiseError('not connected');
 203          }
 204  
 205          $this->blocking = $mode;
 206          socket_set_blocking($this->fp, $this->blocking);
 207          return true;
 208      }
 209  
 210      /**
 211       * Sets the timeout value on socket descriptor,
 212       * expressed in the sum of seconds and microseconds
 213       *
 214       * @param integer $seconds  Seconds.
 215       * @param integer $microseconds  Microseconds.
 216       * @access public
 217       * @return mixed true on success or a PEAR_Error instance otherwise
 218       */
 219      function setTimeout($seconds, $microseconds)
 220      {
 221          if (!is_resource($this->fp)) {
 222              return $this->raiseError('not connected');
 223          }
 224  
 225          return socket_set_timeout($this->fp, $seconds, $microseconds);
 226      }
 227  
 228      /**
 229       * Sets the file buffering size on the stream.
 230       * See php's stream_set_write_buffer for more information.
 231       *
 232       * @param integer $size     Write buffer size.
 233       * @access public
 234       * @return mixed on success or an PEAR_Error object otherwise
 235       */
 236      function setWriteBuffer($size)
 237      {
 238          if (!is_resource($this->fp)) {
 239              return $this->raiseError('not connected');
 240          }
 241  
 242          $returned = stream_set_write_buffer($this->fp, $size);
 243          if ($returned == 0) {
 244              return true;
 245          }
 246          return $this->raiseError('Cannot set write buffer.');
 247      }
 248  
 249      /**
 250       * Returns information about an existing socket resource.
 251       * Currently returns four entries in the result array:
 252       *
 253       * <p>
 254       * timed_out (bool) - The socket timed out waiting for data<br>
 255       * blocked (bool) - The socket was blocked<br>
 256       * eof (bool) - Indicates EOF event<br>
 257       * unread_bytes (int) - Number of bytes left in the socket buffer<br>
 258       * </p>
 259       *
 260       * @access public
 261       * @return mixed Array containing information about existing socket resource or a PEAR_Error instance otherwise
 262       */
 263      function getStatus()
 264      {
 265          if (!is_resource($this->fp)) {
 266              return $this->raiseError('not connected');
 267          }
 268  
 269          return socket_get_status($this->fp);
 270      }
 271  
 272      /**
 273       * Get a specified line of data
 274       *
 275       * @access public
 276       * @return $size bytes of data from the socket, or a PEAR_Error if
 277       *         not connected.
 278       */
 279      function gets($size)
 280      {
 281          if (!is_resource($this->fp)) {
 282              return $this->raiseError('not connected');
 283          }
 284  
 285          return @fgets($this->fp, $size);
 286      }
 287  
 288      /**
 289       * Read a specified amount of data. This is guaranteed to return,
 290       * and has the added benefit of getting everything in one fread()
 291       * chunk; if you know the size of the data you're getting
 292       * beforehand, this is definitely the way to go.
 293       *
 294       * @param integer $size  The number of bytes to read from the socket.
 295       * @access public
 296       * @return $size bytes of data from the socket, or a PEAR_Error if
 297       *         not connected.
 298       */
 299      function read($size)
 300      {
 301          if (!is_resource($this->fp)) {
 302              return $this->raiseError('not connected');
 303          }
 304  
 305          return @fread($this->fp, $size);
 306      }
 307  
 308      /**
 309       * Write a specified amount of data.
 310       *
 311       * @param string  $data       Data to write.
 312       * @param integer $blocksize  Amount of data to write at once.
 313       *                            NULL means all at once.
 314       *
 315       * @access public
 316       * @return mixed If the socket is not connected, returns an instance of PEAR_Error
 317       *               If the write succeeds, returns the number of bytes written
 318       *               If the write fails, returns false.
 319       */
 320      function write($data, $blocksize = null)
 321      {
 322          if (!is_resource($this->fp)) {
 323              return $this->raiseError('not connected');
 324          }
 325  
 326          if (is_null($blocksize) && !OS_WINDOWS) {
 327              return @fwrite($this->fp, $data);
 328          } else {
 329              if (is_null($blocksize)) {
 330                  $blocksize = 1024;
 331              }
 332  
 333              $pos = 0;
 334              $size = strlen($data);
 335              while ($pos < $size) {
 336                  $written = @fwrite($this->fp, substr($data, $pos, $blocksize));
 337                  if ($written === false) {
 338                      return false;
 339                  }
 340                  $pos += $written;
 341              }
 342  
 343              return $pos;
 344          }
 345      }
 346  
 347      /**
 348       * Write a line of data to the socket, followed by a trailing "\r\n".
 349       *
 350       * @access public
 351       * @return mixed fputs result, or an error
 352       */
 353      function writeLine($data)
 354      {
 355          if (!is_resource($this->fp)) {
 356              return $this->raiseError('not connected');
 357          }
 358  
 359          return fwrite($this->fp, $data . "\r\n");
 360      }
 361  
 362      /**
 363       * Tests for end-of-file on a socket descriptor.
 364       *
 365       * Also returns true if the socket is disconnected.
 366       *
 367       * @access public
 368       * @return bool
 369       */
 370      function eof()
 371      {
 372          return (!is_resource($this->fp) || feof($this->fp));
 373      }
 374  
 375      /**
 376       * Reads a byte of data
 377       *
 378       * @access public
 379       * @return 1 byte of data from the socket, or a PEAR_Error if
 380       *         not connected.
 381       */
 382      function readByte()
 383      {
 384          if (!is_resource($this->fp)) {
 385              return $this->raiseError('not connected');
 386          }
 387  
 388          return ord(@fread($this->fp, 1));
 389      }
 390  
 391      /**
 392       * Reads a word of data
 393       *
 394       * @access public
 395       * @return 1 word of data from the socket, or a PEAR_Error if
 396       *         not connected.
 397       */
 398      function readWord()
 399      {
 400          if (!is_resource($this->fp)) {
 401              return $this->raiseError('not connected');
 402          }
 403  
 404          $buf = @fread($this->fp, 2);
 405          return (ord($buf[0]) + (ord($buf[1]) << 8));
 406      }
 407  
 408      /**
 409       * Reads an int of data
 410       *
 411       * @access public
 412       * @return integer  1 int of data from the socket, or a PEAR_Error if
 413       *                  not connected.
 414       */
 415      function readInt()
 416      {
 417          if (!is_resource($this->fp)) {
 418              return $this->raiseError('not connected');
 419          }
 420  
 421          $buf = @fread($this->fp, 4);
 422          return (ord($buf[0]) + (ord($buf[1]) << 8) +
 423                  (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
 424      }
 425  
 426      /**
 427       * Reads a zero-terminated string of data
 428       *
 429       * @access public
 430       * @return string, or a PEAR_Error if
 431       *         not connected.
 432       */
 433      function readString()
 434      {
 435          if (!is_resource($this->fp)) {
 436              return $this->raiseError('not connected');
 437          }
 438  
 439          $string = '';
 440          while (($char = @fread($this->fp, 1)) != "\x00")  {
 441              $string .= $char;
 442          }
 443          return $string;
 444      }
 445  
 446      /**
 447       * Reads an IP Address and returns it in a dot formatted string
 448       *
 449       * @access public
 450       * @return Dot formatted string, or a PEAR_Error if
 451       *         not connected.
 452       */
 453      function readIPAddress()
 454      {
 455          if (!is_resource($this->fp)) {
 456              return $this->raiseError('not connected');
 457          }
 458  
 459          $buf = @fread($this->fp, 4);
 460          return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]),
 461                         ord($buf[2]), ord($buf[3]));
 462      }
 463  
 464      /**
 465       * Read until either the end of the socket or a newline, whichever
 466       * comes first. Strips the trailing newline from the returned data.
 467       *
 468       * @access public
 469       * @return All available data up to a newline, without that
 470       *         newline, or until the end of the socket, or a PEAR_Error if
 471       *         not connected.
 472       */
 473      function readLine()
 474      {
 475          if (!is_resource($this->fp)) {
 476              return $this->raiseError('not connected');
 477          }
 478  
 479          $line = '';
 480          $timeout = time() + $this->timeout;
 481          while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
 482              $line .= @fgets($this->fp, $this->lineLength);
 483              if (substr($line, -1) == "\n") {
 484                  return rtrim($line, "\r\n");
 485              }
 486          }
 487          return $line;
 488      }
 489  
 490      /**
 491       * Read until the socket closes, or until there is no more data in
 492       * the inner PHP buffer. If the inner buffer is empty, in blocking
 493       * mode we wait for at least 1 byte of data. Therefore, in
 494       * blocking mode, if there is no data at all to be read, this
 495       * function will never exit (unless the socket is closed on the
 496       * remote end).
 497       *
 498       * @access public
 499       *
 500       * @return string  All data until the socket closes, or a PEAR_Error if
 501       *                 not connected.
 502       */
 503      function readAll()
 504      {
 505          if (!is_resource($this->fp)) {
 506              return $this->raiseError('not connected');
 507          }
 508  
 509          $data = '';
 510          while (!feof($this->fp)) {
 511              $data .= @fread($this->fp, $this->lineLength);
 512          }
 513          return $data;
 514      }
 515  
 516      /**
 517       * Runs the equivalent of the select() system call on the socket
 518       * with a timeout specified by tv_sec and tv_usec.
 519       *
 520       * @param integer $state    Which of read/write/error to check for.
 521       * @param integer $tv_sec   Number of seconds for timeout.
 522       * @param integer $tv_usec  Number of microseconds for timeout.
 523       *
 524       * @access public
 525       * @return False if select fails, integer describing which of read/write/error
 526       *         are ready, or PEAR_Error if not connected.
 527       */
 528      function select($state, $tv_sec, $tv_usec = 0)
 529      {
 530          if (!is_resource($this->fp)) {
 531              return $this->raiseError('not connected');
 532          }
 533  
 534          $read = null;
 535          $write = null;
 536          $except = null;
 537          if ($state & NET_SOCKET_READ) {
 538              $read[] = $this->fp;
 539          }
 540          if ($state & NET_SOCKET_WRITE) {
 541              $write[] = $this->fp;
 542          }
 543          if ($state & NET_SOCKET_ERROR) {
 544              $except[] = $this->fp;
 545          }
 546          if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) {
 547              return false;
 548          }
 549  
 550          $result = 0;
 551          if (count($read)) {
 552              $result |= NET_SOCKET_READ;
 553          }
 554          if (count($write)) {
 555              $result |= NET_SOCKET_WRITE;
 556          }
 557          if (count($except)) {
 558              $result |= NET_SOCKET_ERROR;
 559          }
 560          return $result;
 561      }
 562  
 563      /**
 564       * Turns encryption on/off on a connected socket.
 565       *
 566       * @param bool    $enabled  Set this parameter to true to enable encryption
 567       *                          and false to disable encryption.
 568       * @param integer $type     Type of encryption. See
 569       *                          http://se.php.net/manual/en/function.stream-socket-enable-crypto.php for values.
 570       *
 571       * @access public
 572       * @return false on error, true on success and 0 if there isn't enough data and the
 573       *         user should try again (non-blocking sockets only). A PEAR_Error object
 574       *         is returned if the socket is not connected
 575       */
 576      function enableCrypto($enabled, $type)
 577      {
 578          if (version_compare(phpversion(), "5.1.0", ">=")) {
 579              if (!is_resource($this->fp)) {
 580                  return $this->raiseError('not connected');
 581              }
 582              return @stream_socket_enable_crypto($this->fp, $enabled, $type);
 583          } else {
 584              return $this->raiseError('Net_Socket::enableCrypto() requires php version >= 5.1.0');
 585          }
 586      }
 587  
 588  }

title

Description

title

Description

title

Description

title

title

Body