PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/common/libraries/plugin/pear/Net/Socket.php

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