PageRenderTime 58ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/modules/Content/includes/phpFlickr/PEAR/Net/Socket.php

https://github.com/DDRJ/Content
PHP | 528 lines | 245 code | 57 blank | 226 comment | 52 complexity | 32cc87d2f930fc9f9695e771ff57669d MD5 | raw file
Possible License(s): 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$
  21. require_once 'PEAR.php';
  22. define('NET_SOCKET_READ', 1);
  23. define('NET_SOCKET_WRITE', 2);
  24. define('NET_SOCKET_ERROR', 3);
  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. * Socket file pointer.
  35. * @var resource $fp
  36. */
  37. var $fp = null;
  38. /**
  39. * Whether the socket is blocking. Defaults to true.
  40. * @var boolean $blocking
  41. */
  42. var $blocking = true;
  43. /**
  44. * Whether the socket is persistent. Defaults to false.
  45. * @var boolean $persistent
  46. */
  47. var $persistent = false;
  48. /**
  49. * The IP address to connect to.
  50. * @var string $addr
  51. */
  52. var $addr = '';
  53. /**
  54. * The port number to connect to.
  55. * @var integer $port
  56. */
  57. var $port = 0;
  58. /**
  59. * Number of seconds to wait on socket connections before assuming
  60. * there's no more data. Defaults to no timeout.
  61. * @var integer $timeout
  62. */
  63. var $timeout = false;
  64. /**
  65. * Number of bytes to read at a time in readLine() and
  66. * readAll(). Defaults to 2048.
  67. * @var integer $lineLength
  68. */
  69. var $lineLength = 2048;
  70. /**
  71. * Connect to the specified port. If called when the socket is
  72. * already connected, it disconnects and connects again.
  73. *
  74. * @param string $addr IP address or host name.
  75. * @param integer $port TCP port number.
  76. * @param boolean $persistent (optional) Whether the connection is
  77. * persistent (kept open between requests
  78. * by the web server).
  79. * @param integer $timeout (optional) How long to wait for data.
  80. * @param array $options See options for stream_context_create.
  81. *
  82. * @access public
  83. *
  84. * @return boolean | PEAR_Error True on success or a PEAR_Error on failure.
  85. */
  86. function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null)
  87. {
  88. if (is_resource($this->fp)) {
  89. @fclose($this->fp);
  90. $this->fp = null;
  91. }
  92. if (!$addr) {
  93. return $this->raiseError('$addr cannot be empty');
  94. } elseif (strspn($addr, '.0123456789') == strlen($addr) ||
  95. strstr($addr, '/') !== false) {
  96. $this->addr = $addr;
  97. } else {
  98. $this->addr = @gethostbyname($addr);
  99. }
  100. $this->port = $port % 65536;
  101. if ($persistent !== null) {
  102. $this->persistent = $persistent;
  103. }
  104. if ($timeout !== null) {
  105. $this->timeout = $timeout;
  106. }
  107. $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
  108. $errno = 0;
  109. $errstr = '';
  110. if ($options && function_exists('stream_context_create')) {
  111. if ($this->timeout) {
  112. $timeout = $this->timeout;
  113. } else {
  114. $timeout = 0;
  115. }
  116. $context = stream_context_create($options);
  117. $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
  118. } else {
  119. if ($this->timeout) {
  120. $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
  121. } else {
  122. $fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
  123. }
  124. }
  125. if (!$fp) {
  126. return $this->raiseError($errstr, $errno);
  127. }
  128. $this->fp = $fp;
  129. return $this->setBlocking($this->blocking);
  130. }
  131. /**
  132. * Disconnects from the peer, closes the socket.
  133. *
  134. * @access public
  135. * @return mixed true on success or an error object otherwise
  136. */
  137. function disconnect()
  138. {
  139. if (!is_resource($this->fp)) {
  140. return $this->raiseError('not connected');
  141. }
  142. @fclose($this->fp);
  143. $this->fp = null;
  144. return true;
  145. }
  146. /**
  147. * Find out if the socket is in blocking mode.
  148. *
  149. * @access public
  150. * @return boolean The current blocking mode.
  151. */
  152. function isBlocking()
  153. {
  154. return $this->blocking;
  155. }
  156. /**
  157. * Sets whether the socket connection should be blocking or
  158. * not. A read call to a non-blocking socket will return immediately
  159. * if there is no data available, whereas it will block until there
  160. * is data for blocking sockets.
  161. *
  162. * @param boolean $mode True for blocking sockets, false for nonblocking.
  163. * @access public
  164. * @return mixed true on success or an error object otherwise
  165. */
  166. function setBlocking($mode)
  167. {
  168. if (!is_resource($this->fp)) {
  169. return $this->raiseError('not connected');
  170. }
  171. $this->blocking = $mode;
  172. socket_set_blocking($this->fp, $this->blocking);
  173. return true;
  174. }
  175. /**
  176. * Sets the timeout value on socket descriptor,
  177. * expressed in the sum of seconds and microseconds
  178. *
  179. * @param integer $seconds Seconds.
  180. * @param integer $microseconds Microseconds.
  181. * @access public
  182. * @return mixed true on success or an error object otherwise
  183. */
  184. function setTimeout($seconds, $microseconds)
  185. {
  186. if (!is_resource($this->fp)) {
  187. return $this->raiseError('not connected');
  188. }
  189. return socket_set_timeout($this->fp, $seconds, $microseconds);
  190. }
  191. /**
  192. * Returns information about an existing socket resource.
  193. * Currently returns four entries in the result array:
  194. *
  195. * <p>
  196. * timed_out (bool) - The socket timed out waiting for data<br>
  197. * blocked (bool) - The socket was blocked<br>
  198. * eof (bool) - Indicates EOF event<br>
  199. * unread_bytes (int) - Number of bytes left in the socket buffer<br>
  200. * </p>
  201. *
  202. * @access public
  203. * @return mixed Array containing information about existing socket resource or an error object otherwise
  204. */
  205. function getStatus()
  206. {
  207. if (!is_resource($this->fp)) {
  208. return $this->raiseError('not connected');
  209. }
  210. return socket_get_status($this->fp);
  211. }
  212. /**
  213. * Get a specified line of data
  214. *
  215. * @access public
  216. * @return $size bytes of data from the socket, or a PEAR_Error if
  217. * not connected.
  218. */
  219. function gets($size)
  220. {
  221. if (!is_resource($this->fp)) {
  222. return $this->raiseError('not connected');
  223. }
  224. return @fgets($this->fp, $size);
  225. }
  226. /**
  227. * Read a specified amount of data. This is guaranteed to return,
  228. * and has the added benefit of getting everything in one fread()
  229. * chunk; if you know the size of the data you're getting
  230. * beforehand, this is definitely the way to go.
  231. *
  232. * @param integer $size The number of bytes to read from the socket.
  233. * @access public
  234. * @return $size bytes of data from the socket, or a PEAR_Error if
  235. * not connected.
  236. */
  237. function read($size)
  238. {
  239. if (!is_resource($this->fp)) {
  240. return $this->raiseError('not connected');
  241. }
  242. return @fread($this->fp, $size);
  243. }
  244. /**
  245. * Write a specified amount of data.
  246. *
  247. * @param string $data Data to write.
  248. * @param integer $blocksize Amount of data to write at once.
  249. * NULL means all at once.
  250. *
  251. * @access public
  252. * @return mixed true on success or an error object otherwise
  253. */
  254. function write($data, $blocksize = null)
  255. {
  256. if (!is_resource($this->fp)) {
  257. return $this->raiseError('not connected');
  258. }
  259. if (is_null($blocksize) && !OS_WINDOWS) {
  260. return fwrite($this->fp, $data);
  261. } else {
  262. if (is_null($blocksize)) {
  263. $blocksize = 1024;
  264. }
  265. $pos = 0;
  266. $size = strlen($data);
  267. while ($pos < $size) {
  268. $written = @fwrite($this->fp, substr($data, $pos, $blocksize));
  269. if ($written === false) {
  270. return false;
  271. }
  272. $pos += $written;
  273. }
  274. return $pos;
  275. }
  276. }
  277. /**
  278. * Write a line of data to the socket, followed by a trailing "\r\n".
  279. *
  280. * @access public
  281. * @return mixed fputs result, or an error
  282. */
  283. function writeLine($data)
  284. {
  285. if (!is_resource($this->fp)) {
  286. return $this->raiseError('not connected');
  287. }
  288. return fwrite($this->fp, $data . "\r\n");
  289. }
  290. /**
  291. * Tests for end-of-file on a socket descriptor.
  292. *
  293. * @access public
  294. * @return bool
  295. */
  296. function eof()
  297. {
  298. return (is_resource($this->fp) && feof($this->fp));
  299. }
  300. /**
  301. * Reads a byte of data
  302. *
  303. * @access public
  304. * @return 1 byte of data from the socket, or a PEAR_Error if
  305. * not connected.
  306. */
  307. function readByte()
  308. {
  309. if (!is_resource($this->fp)) {
  310. return $this->raiseError('not connected');
  311. }
  312. return ord(@fread($this->fp, 1));
  313. }
  314. /**
  315. * Reads a word of data
  316. *
  317. * @access public
  318. * @return 1 word of data from the socket, or a PEAR_Error if
  319. * not connected.
  320. */
  321. function readWord()
  322. {
  323. if (!is_resource($this->fp)) {
  324. return $this->raiseError('not connected');
  325. }
  326. $buf = @fread($this->fp, 2);
  327. return (ord($buf[0]) + (ord($buf[1]) << 8));
  328. }
  329. /**
  330. * Reads an int of data
  331. *
  332. * @access public
  333. * @return integer 1 int of data from the socket, or a PEAR_Error if
  334. * not connected.
  335. */
  336. function readInt()
  337. {
  338. if (!is_resource($this->fp)) {
  339. return $this->raiseError('not connected');
  340. }
  341. $buf = @fread($this->fp, 4);
  342. return (ord($buf[0]) + (ord($buf[1]) << 8) +
  343. (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
  344. }
  345. /**
  346. * Reads a zero-terminated string of data
  347. *
  348. * @access public
  349. * @return string, or a PEAR_Error if
  350. * not connected.
  351. */
  352. function readString()
  353. {
  354. if (!is_resource($this->fp)) {
  355. return $this->raiseError('not connected');
  356. }
  357. $string = '';
  358. while (($char = @fread($this->fp, 1)) != "\x00") {
  359. $string .= $char;
  360. }
  361. return $string;
  362. }
  363. /**
  364. * Reads an IP Address and returns it in a dot formated string
  365. *
  366. * @access public
  367. * @return Dot formated string, or a PEAR_Error if
  368. * not connected.
  369. */
  370. function readIPAddress()
  371. {
  372. if (!is_resource($this->fp)) {
  373. return $this->raiseError('not connected');
  374. }
  375. $buf = @fread($this->fp, 4);
  376. return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]),
  377. ord($buf[2]), ord($buf[3]));
  378. }
  379. /**
  380. * Read until either the end of the socket or a newline, whichever
  381. * comes first. Strips the trailing newline from the returned data.
  382. *
  383. * @access public
  384. * @return All available data up to a newline, without that
  385. * newline, or until the end of the socket, or a PEAR_Error if
  386. * not connected.
  387. */
  388. function readLine()
  389. {
  390. if (!is_resource($this->fp)) {
  391. return $this->raiseError('not connected');
  392. }
  393. $line = '';
  394. $timeout = time() + $this->timeout;
  395. while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
  396. $line .= @fgets($this->fp, $this->lineLength);
  397. if (substr($line, -1) == "\n") {
  398. return rtrim($line, "\r\n");
  399. }
  400. }
  401. return $line;
  402. }
  403. /**
  404. * Read until the socket closes, or until there is no more data in
  405. * the inner PHP buffer. If the inner buffer is empty, in blocking
  406. * mode we wait for at least 1 byte of data. Therefore, in
  407. * blocking mode, if there is no data at all to be read, this
  408. * function will never exit (unless the socket is closed on the
  409. * remote end).
  410. *
  411. * @access public
  412. *
  413. * @return string All data until the socket closes, or a PEAR_Error if
  414. * not connected.
  415. */
  416. function readAll()
  417. {
  418. if (!is_resource($this->fp)) {
  419. return $this->raiseError('not connected');
  420. }
  421. $data = '';
  422. while (!feof($this->fp)) {
  423. $data .= @fread($this->fp, $this->lineLength);
  424. }
  425. return $data;
  426. }
  427. /**
  428. * Runs the equivalent of the select() system call on the socket
  429. * with a timeout specified by tv_sec and tv_usec.
  430. *
  431. * @param integer $state Which of read/write/error to check for.
  432. * @param integer $tv_sec Number of seconds for timeout.
  433. * @param integer $tv_usec Number of microseconds for timeout.
  434. *
  435. * @access public
  436. * @return False if select fails, integer describing which of read/write/error
  437. * are ready, or PEAR_Error if not connected.
  438. */
  439. function select($state, $tv_sec, $tv_usec = 0)
  440. {
  441. if (!is_resource($this->fp)) {
  442. return $this->raiseError('not connected');
  443. }
  444. $read = null;
  445. $write = null;
  446. $except = null;
  447. if ($state & NET_SOCKET_READ) {
  448. $read[] = $this->fp;
  449. }
  450. if ($state & NET_SOCKET_WRITE) {
  451. $write[] = $this->fp;
  452. }
  453. if ($state & NET_SOCKET_ERROR) {
  454. $except[] = $this->fp;
  455. }
  456. if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) {
  457. return false;
  458. }
  459. $result = 0;
  460. if (count($read)) {
  461. $result |= NET_SOCKET_READ;
  462. }
  463. if (count($write)) {
  464. $result |= NET_SOCKET_WRITE;
  465. }
  466. if (count($except)) {
  467. $result |= NET_SOCKET_ERROR;
  468. }
  469. return $result;
  470. }
  471. }