KerioApiSocket.php 5.6 KB

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