KerioApiSocket.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <?php
  2. /**
  3. * This file is part of the kerio-api-php.
  4. *
  5. * Copyright (c) Kerio Technologies s.r.o.
  6. *
  7. * For the full copyright and license information, please view
  8. * the file license.txt that was distributed with this source code
  9. * or visit Developer Zone. (http://www.kerio.com/developers)
  10. *
  11. * Do not modify this source code.
  12. * Any changes may be overwritten by a new version.
  13. */
  14. require_once(dirname(__FILE__) . '/KerioApiSocketInterface.php');
  15. /**
  16. * Kerio API Socket Class.
  17. *
  18. * This class implements basic methods used in HTTP communication.
  19. *
  20. * @copyright Copyright &copy; 2012-2012 Kerio Technologies s.r.o.
  21. * @license http://www.kerio.com/developers/license/sdk-agreement
  22. * @version 1.4.0.234
  23. */
  24. class KerioApiSocket implements KerioApiSocketInterface {
  25. /**
  26. * Socket buffer size
  27. */
  28. const BUFFER_SIZE = 10240;
  29. /**
  30. * Socket handler
  31. * @var resource
  32. */
  33. private $socketHandler = '';
  34. /**
  35. * Communication timeout
  36. * @var integer
  37. */
  38. private $timeout = 10;
  39. /**
  40. * Server hostname
  41. * @var string
  42. */
  43. private $hostname = '';
  44. /**
  45. * Server port
  46. * @var integer
  47. */
  48. private $port = '';
  49. /**
  50. * SSL encryption
  51. * @var string
  52. */
  53. private $cipher = 'ssl://';
  54. /**
  55. * Headers
  56. * @var string
  57. */
  58. private $headers = '';
  59. /**
  60. * Body
  61. * @var string
  62. */
  63. private $body = '';
  64. /**
  65. * Socker error message
  66. * @var string
  67. */
  68. private $errorMessage = '';
  69. /**
  70. * Socker error code
  71. * @var integer
  72. */
  73. private $errorCode = 0;
  74. /**
  75. * Class constructor.
  76. *
  77. * @param string Hostname
  78. * @param integer Port
  79. * @param integer Timeout, optional
  80. * @return boolean True on success
  81. */
  82. public function KerioApiSocket($hostname, $port, $timeout = '') {
  83. /* Set host */
  84. $this->hostname = $hostname;
  85. $this->port = $port;
  86. /* Set timeout */
  87. if (is_int($timeout)) {
  88. $this->timeout = $timeout;
  89. }
  90. /* Open socket to server */
  91. $this->open();
  92. return ($this->socketHandler) ? TRUE : FALSE;
  93. }
  94. /**
  95. * Class desctructor.
  96. *
  97. * @param void
  98. * @return void
  99. */
  100. public function __destruct() {
  101. $this->close();
  102. }
  103. /**
  104. * Open socket to server.
  105. *
  106. * @param void
  107. * @return void
  108. */
  109. protected function open() {
  110. $errstr = "";
  111. $errno = "";
  112. $context = stream_context_create();
  113. stream_context_set_option($context, "ssl", "allow_self_signed", true);
  114. stream_context_set_option($context, "ssl", "verify_peer", false);
  115. stream_context_set_option($context, "ssl", "verify_peer_name", false);
  116. $this->socketHandler = @stream_socket_client($this->cipher . $this->hostname . ':' . $this->port, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context);
  117. $this->errorCode = $errno;
  118. $this->errorMessage = $errstr;
  119. }
  120. /**
  121. * Close socket to server.
  122. *
  123. * @param void
  124. * @return void
  125. */
  126. protected function close() {
  127. @fclose($this->socketHandler);
  128. unset($this->socketHandler);
  129. }
  130. /**
  131. * Send data to socket.
  132. *
  133. * @see class/KerioApiSocketInterface::send()
  134. * @param string Data to socket
  135. * @return string Data from socket
  136. * @throws KerioApiException
  137. */
  138. public function send($data) {
  139. if ($this->checkConnection()) {
  140. @fwrite($this->socketHandler, $data);
  141. return $this->read();
  142. }
  143. else {
  144. throw new KerioApiException(sprintf("Cannot connect to %s using port %d.", $this->hostname, $this->port));
  145. }
  146. }
  147. /**
  148. * Read data from socket.
  149. *
  150. * @param void
  151. * @return string HTTP data from socket
  152. * @throws KerioApiExceptions
  153. */
  154. protected function read() {
  155. if ($this->socketHandler) {
  156. $response = '';
  157. while (FALSE === feof($this->socketHandler)) {
  158. $response .= fgets($this->socketHandler, self::BUFFER_SIZE);
  159. }
  160. list($this->headers, $this->body) = explode("\r\n\r\n", $response);
  161. if (FALSE !== strpos(strtolower($this->headers), 'transfer-encoding: chunked')) {
  162. $this->unchunkHttp();
  163. }
  164. return $response;
  165. }
  166. else {
  167. throw new KerioApiException('Cannot read data from server, connection timeout.');
  168. }
  169. }
  170. /**
  171. * Unchunk HTTP/1.1 body.
  172. *
  173. * @param void
  174. * @return void
  175. */
  176. private function unchunkHttp() {
  177. $body = $this->body;
  178. for ($new = ''; !empty($body); $str = trim($body)) {
  179. $pos = strpos($body, "\r\n");
  180. $len = hexdec(substr($body, 0, $pos));
  181. $new .= substr($body, $pos + 2, $len);
  182. $body = substr($body, $pos + 2 + $len);
  183. }
  184. $this->body = $new;
  185. }
  186. /**
  187. * Set connection encryption to ssl://
  188. *
  189. * @param boolen True if ssl:// is used
  190. * @return void
  191. */
  192. public function setEncryption($boolean) {
  193. $this->cipher = ($boolean) ? 'ssl://' : '';
  194. }
  195. /**
  196. * Check connection to server.
  197. *
  198. * @param void
  199. * @return boolean True on success
  200. */
  201. public final function checkConnection() {
  202. if ($this->checkHost()) {
  203. $socket = @fsockopen($this->hostname, $this->port, $errno, $errstr, $this->timeout);
  204. $this->errorCode = $errno;
  205. $this->errorMessage = $errstr;
  206. return ($socket) ? TRUE : FALSE;
  207. }
  208. else {
  209. return FALSE;
  210. }
  211. }
  212. /**
  213. * Check if DNS host is valid.
  214. *
  215. * @param void
  216. * @return boolean True on success
  217. */
  218. public final function checkHost() {
  219. return gethostbyname($this->hostname) ? TRUE : FALSE;
  220. }
  221. /**
  222. * Get headers.
  223. *
  224. * @param void
  225. * @return string
  226. */
  227. public final function getHeaders() {
  228. return $this->headers;
  229. }
  230. /**
  231. * Get body.
  232. *
  233. * @param void
  234. * @return string
  235. */
  236. public final function getBody() {
  237. return $this->body;
  238. }
  239. /**
  240. * Get socker error message.
  241. *
  242. * @param void
  243. * @return string
  244. */
  245. public final function getErrorMessage() {
  246. return $this->errorMessage;
  247. }
  248. /**
  249. * Get socket error code.
  250. *
  251. * @param void
  252. * @return integer
  253. */
  254. public final function getErrorCode() {
  255. return $this->errorCode;
  256. }
  257. }