fix calendar css, take 2. (#213)
[openemr.git] / interface / modules / zend_modules / library / Zend / Mail / Protocol / Pop3.php
blob6a9eb14192a6057e4ad9bd94730ee8b61f12210e
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Mail\Protocol;
12 use Zend\Stdlib\ErrorHandler;
14 class Pop3
16 /**
17 * Default timeout in seconds for initiating session
19 const TIMEOUT_CONNECTION = 30;
21 /**
22 * saves if server supports top
23 * @var null|bool
25 public $hasTop = null;
27 /**
28 * socket to pop3
29 * @var null|resource
31 protected $socket;
33 /**
34 * greeting timestamp for apop
35 * @var null|string
37 protected $timestamp;
39 /**
40 * Public constructor
42 * @param string $host hostname or IP address of POP3 server, if given connect() is called
43 * @param int|null $port port of POP3 server, null for default (110 or 995 for ssl)
44 * @param bool|string $ssl use ssl? 'SSL', 'TLS' or false
46 public function __construct($host = '', $port = null, $ssl = false)
48 if ($host) {
49 $this->connect($host, $port, $ssl);
53 /**
54 * Public destructor
56 public function __destruct()
58 $this->logout();
61 /**
62 * Open connection to POP3 server
64 * @param string $host hostname or IP address of POP3 server
65 * @param int|null $port of POP3 server, default is 110 (995 for ssl)
66 * @param string|bool $ssl use 'SSL', 'TLS' or false
67 * @throws Exception\RuntimeException
68 * @return string welcome message
70 public function connect($host, $port = null, $ssl = false)
72 $isTls = false;
74 if ($ssl) {
75 $ssl = strtolower($ssl);
78 switch ($ssl) {
79 case 'ssl':
80 $host = 'ssl://' . $host;
81 if (!$port) {
82 $port = 995;
84 break;
85 case 'tls':
86 $isTls = true;
87 // break intentionally omitted
88 default:
89 if (!$port) {
90 $port = 110;
94 ErrorHandler::start();
95 $this->socket = fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION);
96 $error = ErrorHandler::stop();
97 if (!$this->socket) {
98 throw new Exception\RuntimeException(sprintf(
99 'cannot connect to host %s',
100 ($error ? sprintf('; error = %s (errno = %d )', $error->getMessage(), $error->getCode()) : '')
101 ), 0, $error);
104 $welcome = $this->readResponse();
106 strtok($welcome, '<');
107 $this->timestamp = strtok('>');
108 if (!strpos($this->timestamp, '@')) {
109 $this->timestamp = null;
110 } else {
111 $this->timestamp = '<' . $this->timestamp . '>';
114 if ($isTls) {
115 $this->request('STLS');
116 $result = stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
117 if (!$result) {
118 throw new Exception\RuntimeException('cannot enable TLS');
122 return $welcome;
126 * Send a request
128 * @param string $request your request without newline
129 * @throws Exception\RuntimeException
131 public function sendRequest($request)
133 ErrorHandler::start();
134 $result = fputs($this->socket, $request . "\r\n");
135 $error = ErrorHandler::stop();
136 if (!$result) {
137 throw new Exception\RuntimeException('send failed - connection closed?', 0, $error);
142 * read a response
144 * @param bool $multiline response has multiple lines and should be read until "<nl>.<nl>"
145 * @throws Exception\RuntimeException
146 * @return string response
148 public function readResponse($multiline = false)
150 ErrorHandler::start();
151 $result = fgets($this->socket);
152 $error = ErrorHandler::stop();
153 if (!is_string($result)) {
154 throw new Exception\RuntimeException('read failed - connection closed?', 0, $error);
157 $result = trim($result);
158 if (strpos($result, ' ')) {
159 list($status, $message) = explode(' ', $result, 2);
160 } else {
161 $status = $result;
162 $message = '';
165 if ($status != '+OK') {
166 throw new Exception\RuntimeException('last request failed');
169 if ($multiline) {
170 $message = '';
171 $line = fgets($this->socket);
172 while ($line && rtrim($line, "\r\n") != '.') {
173 if ($line[0] == '.') {
174 $line = substr($line, 1);
176 $message .= $line;
177 $line = fgets($this->socket);
181 return $message;
185 * Send request and get response
187 * @see sendRequest()
188 * @see readResponse()
189 * @param string $request request
190 * @param bool $multiline multiline response?
191 * @return string result from readResponse()
193 public function request($request, $multiline = false)
195 $this->sendRequest($request);
196 return $this->readResponse($multiline);
200 * End communication with POP3 server (also closes socket)
202 public function logout()
204 if ($this->socket) {
205 try {
206 $this->request('QUIT');
207 } catch (Exception\ExceptionInterface $e) {
208 // ignore error - we're closing the socket anyway
211 fclose($this->socket);
212 $this->socket = null;
218 * Get capabilities from POP3 server
220 * @return array list of capabilities
222 public function capa()
224 $result = $this->request('CAPA', true);
225 return explode("\n", $result);
230 * Login to POP3 server. Can use APOP
232 * @param string $user username
233 * @param string $password password
234 * @param bool $tryApop should APOP be tried?
236 public function login($user, $password, $tryApop = true)
238 if ($tryApop && $this->timestamp) {
239 try {
240 $this->request("APOP $user " . md5($this->timestamp . $password));
241 return;
242 } catch (Exception\ExceptionInterface $e) {
243 // ignore
247 $this->request("USER $user");
248 $this->request("PASS $password");
253 * Make STAT call for message count and size sum
255 * @param int $messages out parameter with count of messages
256 * @param int $octets out parameter with size in octets of messages
258 public function status(&$messages, &$octets)
260 $messages = 0;
261 $octets = 0;
262 $result = $this->request('STAT');
264 list($messages, $octets) = explode(' ', $result);
269 * Make LIST call for size of message(s)
271 * @param int|null $msgno number of message, null for all
272 * @return int|array size of given message or list with array(num => size)
274 public function getList($msgno = null)
276 if ($msgno !== null) {
277 $result = $this->request("LIST $msgno");
279 list(, $result) = explode(' ', $result);
280 return (int) $result;
283 $result = $this->request('LIST', true);
284 $messages = array();
285 $line = strtok($result, "\n");
286 while ($line) {
287 list($no, $size) = explode(' ', trim($line));
288 $messages[(int) $no] = (int) $size;
289 $line = strtok("\n");
292 return $messages;
297 * Make UIDL call for getting a uniqueid
299 * @param int|null $msgno number of message, null for all
300 * @return string|array uniqueid of message or list with array(num => uniqueid)
302 public function uniqueid($msgno = null)
304 if ($msgno !== null) {
305 $result = $this->request("UIDL $msgno");
307 list(, $result) = explode(' ', $result);
308 return $result;
311 $result = $this->request('UIDL', true);
313 $result = explode("\n", $result);
314 $messages = array();
315 foreach ($result as $line) {
316 if (!$line) {
317 continue;
319 list($no, $id) = explode(' ', trim($line), 2);
320 $messages[(int) $no] = $id;
323 return $messages;
328 * Make TOP call for getting headers and maybe some body lines
329 * This method also sets hasTop - before it it's not known if top is supported
331 * The fallback makes normal RETR call, which retrieves the whole message. Additional
332 * lines are not removed.
334 * @param int $msgno number of message
335 * @param int $lines number of wanted body lines (empty line is inserted after header lines)
336 * @param bool $fallback fallback with full retrieve if top is not supported
337 * @throws Exception\RuntimeException
338 * @throws Exception\ExceptionInterface
339 * @return string message headers with wanted body lines
341 public function top($msgno, $lines = 0, $fallback = false)
343 if ($this->hasTop === false) {
344 if ($fallback) {
345 return $this->retrieve($msgno);
346 } else {
347 throw new Exception\RuntimeException('top not supported and no fallback wanted');
350 $this->hasTop = true;
352 $lines = (!$lines || $lines < 1) ? 0 : (int) $lines;
354 try {
355 $result = $this->request("TOP $msgno $lines", true);
356 } catch (Exception\ExceptionInterface $e) {
357 $this->hasTop = false;
358 if ($fallback) {
359 $result = $this->retrieve($msgno);
360 } else {
361 throw $e;
365 return $result;
369 * Make a RETR call for retrieving a full message with headers and body
371 * @param int $msgno message number
372 * @return string message
374 public function retrieve($msgno)
376 $result = $this->request("RETR $msgno", true);
377 return $result;
381 * Make a NOOP call, maybe needed for keeping the server happy
383 public function noop()
385 $this->request('NOOP');
389 * Make a DELE count to remove a message
391 * @param $msgno
393 public function delete($msgno)
395 $this->request("DELE $msgno");
399 * Make RSET call, which rollbacks delete requests
401 public function undelete()
403 $this->request('RSET');