fp)) { @fclose($this->fp); $this->fp = null; } // convert hostname to ip address if (!$addr) { return $this->raiseError('host address cannot be empty'); } elseif (strspn($addr, '.0123456789') == strlen($addr) || strstr($addr, '/') !== false) { $this->addr = $addr; } else { $this->addr = @gethostbyname($addr); } $this->port = $port % 65536; if ($persistent !== null) { $this->persistent = $persistent; } if ($timeout !== null) { $this->timeout = $timeout; } $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; $errno = 0; $errstr = ''; if ($this->timeout) { $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout); } else { $fp = @$openfunc($this->addr, $this->port, $errno, $errstr); } if (!$fp) { return $this->raiseError($errstr, Array($errno)); } $this->fp = $fp; return $this->setBlocking($this->blocking); } /** * Disconnects from the peer, closes the socket. * * @access public * @return mixed true on success or an error object otherwise */ function disconnect() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } @fclose($this->fp); $this->fp = null; return true; } /** * Find out if the socket is in blocking mode. * * @access public * @return boolean The current blocking mode. */ function isBlocking() { return $this->blocking; } /** * Sets whether the socket connection should be blocking or * not. A read call to a non-blocking socket will return immediately * if there is no data available, whereas it will block until there * is data for blocking sockets. * * @param boolean $mode True for blocking sockets, false for nonblocking. * @access public * @return mixed true on success or an error object otherwise */ function setBlocking($mode) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $this->blocking = $mode; socket_set_blocking($this->fp, $this->blocking); return true; } /** * Sets the timeout value on socket descriptor, * expressed in the sum of seconds and microseconds * * @param integer $seconds Seconds. * @param integer $microseconds Microseconds. * @access public * @return mixed true on success or an error object otherwise */ function setTimeout($seconds, $microseconds) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return socket_set_timeout($this->fp, $seconds, $microseconds); } /** * Returns information about an existing socket resource. * Currently returns four entries in the result array: * *

* timed_out (bool) - The socket timed out waiting for data
* blocked (bool) - The socket was blocked
* eof (bool) - Indicates EOF event
* unread_bytes (int) - Number of bytes left in the socket buffer
*

* * @access public * @return mixed Array containing information about existing socket resource or an error object otherwise */ function getStatus() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return socket_get_status($this->fp); } /** * Get a specified line of data * * @access public * @return $size bytes of data from the socket, or a PEAR_Error if * not connected. */ function gets($size) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return @fgets($this->fp, $size); } /** * Read a specified amount of data. This is guaranteed to return, * and has the added benefit of getting everything in one fread() * chunk; if you know the size of the data you're getting * beforehand, this is definitely the way to go. * * @param integer $size The number of bytes to read from the socket. * @access public * @return $size bytes of data from the socket, or a PEAR_Error if * not connected. */ function read($size) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return @fread($this->fp, $size); } /** * Write a specified amount of data. * * @param string $data Data to write. * @param integer $blocksize Amount of data to write at once. * NULL means all at once. * * @access public * @return mixed true on success or an error object otherwise */ function write($data, $blocksize = null) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } if (is_null($blocksize) && (substr(PHP_OS, 0, 3) != 'WIN')) { return fwrite($this->fp, $data); } else { if (is_null($blocksize)) { $blocksize = 1024; } $pos = 0; $size = strlen($data); while ($pos < $size) { $written = @fwrite($this->fp, substr($data, $pos, $blocksize)); if ($written === false) { return false; } $pos += $written; } return $pos; } } /** * Write a line of data to the socket, followed by a trailing "\r\n". * * @access public * @return mixed fputs result, or an error */ function writeLine($data) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } return fwrite($this->fp, $data . "\r\n"); } /** * Tests for end-of-file on a socket descriptor. * * @access public * @return bool */ function eof() { return (is_resource($this->fp) && feof($this->fp)); } /** * Read until either the end of the socket or a newline, whichever * comes first. Strips the trailing newline from the returned data. * * @access public * @return All available data up to a newline, without that * newline, or until the end of the socket, or a PEAR_Error if * not connected. */ function readLine() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $line = ''; $timeout = time() + $this->timeout; while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) { $line .= @fgets($this->fp, $this->lineLength); if (substr($line, -1) == "\n") { return rtrim($line, "\r\n"); } } return $line; } /** * Read until the socket closes, or until there is no more data in * the inner PHP buffer. If the inner buffer is empty, in blocking * mode we wait for at least 1 byte of data. Therefore, in * blocking mode, if there is no data at all to be read, this * function will never exit (unless the socket is closed on the * remote end). * * @access public * * @return string All data until the socket closes, or a PEAR_Error if * not connected. */ function readAll() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $data = ''; while (!feof($this->fp)) { $data .= @fread($this->fp, $this->lineLength); } return $data; } function raiseError($text, $params = Array()) { trigger_error(vsprintf($text, $params), E_USER_WARNING); return false; } }