1 <?php
2 3 4 5 6 7 8 9 10 11 12 13
14
15 require_once(dirname(__FILE__) . '/KerioApiSocketInterface.php');
16
17 18 19 20 21 22 23 24 25
26 class KerioApiSocket implements KerioApiSocketInterface {
27
28 29 30
31 const BUFFER_SIZE = 10240;
32
33 34 35 36
37 private $socketHandler = '';
38
39 40 41 42
43 private $timeout = 10;
44
45 46 47 48
49 private $hostname = '';
50
51 52 53 54
55 private $port = '';
56
57 58 59 60
61 private $cipher = 'ssl://';
62
63 64 65 66
67 private = '';
68
69 70 71 72
73 private $body = '';
74
75 76 77 78
79 private $errorMessage = '';
80
81 82 83 84
85 private $errorCode = 0;
86
87 88 89 90 91 92 93 94
95 public function KerioApiSocket($hostname, $port, $timeout = '') {
96
97 $this->hostname = $hostname;
98 $this->port = $port;
99
100
101 if (is_int($timeout)) {
102 $this->timeout = $timeout;
103 }
104
105
106 $this->open();
107 return ($this->socketHandler) ? TRUE : FALSE;
108 }
109
110 111 112 113 114 115
116 public function __destruct() {
117 $this->close();
118 }
119
120 121 122 123 124 125
126 protected function open() {
127 $errstr = "";
128 $errno = "";
129 $context = stream_context_create();
130 stream_context_set_option($context, "ssl", "allow_self_signed", true);
131 stream_context_set_option($context, "ssl", "verify_peer", false);
132 stream_context_set_option($context, "ssl", "verify_peer_name", false);
133 $this->socketHandler = @stream_socket_client($this->cipher . $this->hostname . ':' . $this->port, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context);
134 $this->errorCode = $errno;
135 $this->errorMessage = $errstr;
136 }
137
138 139 140 141 142 143
144 protected function close() {
145 @fclose($this->socketHandler);
146 unset($this->socketHandler);
147 }
148
149 150 151 152 153 154 155 156
157 public function send($data) {
158 if ($this->checkConnection()) {
159 @fwrite($this->socketHandler, $data);
160 return $this->read();
161 }
162 else {
163 throw new KerioApiException(sprintf("Cannot connect to %s using port %d.", $this->hostname, $this->port));
164 }
165 }
166
167 168 169 170 171 172 173
174 protected function read() {
175 if ($this->socketHandler) {
176 $response = '';
177 while (FALSE === feof($this->socketHandler)) {
178 $response .= fgets($this->socketHandler, self::BUFFER_SIZE);
179 }
180
181 list($this->headers, $this->body) = explode("\r\n\r\n", $response);
182
183 if (FALSE !== strpos(strtolower($this->headers), 'transfer-encoding: chunked')) {
184 $this->unchunkHttp();
185 }
186
187 return $response;
188 }
189 else {
190 throw new KerioApiException('Cannot read data from server, connection timeout.');
191 }
192 }
193
194 195 196 197 198 199
200 private function unchunkHttp() {
201 $body = $this->body;
202 for ($new = ''; !empty($body); $str = trim($body)) {
203 $pos = strpos($body, "\r\n");
204 $len = hexdec(substr($body, 0, $pos));
205 $new .= substr($body, $pos + 2, $len);
206 $body = substr($body, $pos + 2 + $len);
207 }
208 $this->body = $new;
209 }
210
211 212 213 214 215 216
217 public function setEncryption($boolean) {
218 $this->cipher = ($boolean) ? 'ssl://' : '';
219 }
220
221 222 223 224 225 226
227 public final function checkConnection() {
228 if ($this->checkHost()) {
229 $socket = @fsockopen($this->hostname, $this->port, $errno, $errstr, $this->timeout);
230 $this->errorCode = $errno;
231 $this->errorMessage = $errstr;
232 return ($socket) ? TRUE : FALSE;
233 }
234 else {
235 return FALSE;
236 }
237 }
238
239 240 241 242 243 244
245 public final function checkHost() {
246 return gethostbyname($this->hostname) ? TRUE : FALSE;
247 }
248
249 250 251 252 253 254
255 public final function () {
256 return $this->headers;
257 }
258
259 260 261 262 263 264
265 public final function getBody() {
266 return $this->body;
267 }
268
269 270 271 272 273 274
275 public final function getErrorMessage() {
276 return $this->errorMessage;
277 }
278
279 280 281 282 283 284
285 public final function getErrorCode() {
286 return $this->errorCode;
287 }
288 }
289
290