| | |
| | | * |
| | | * @param int Number of bytes sent, False on error |
| | | */ |
| | | function putLine($string, $endln = true, $anonymized = false) |
| | | protected function putLine($string, $endln = true, $anonymized = false) |
| | | { |
| | | if (!$this->fp) { |
| | | return false; |
| | |
| | | $this->debug('C: ' . $log); |
| | | } |
| | | |
| | | $res = fwrite($this->fp, $string . ($endln ? "\r\n" : '')); |
| | | if ($endln) { |
| | | $string .= "\r\n"; |
| | | } |
| | | |
| | | $res = fwrite($this->fp, $string); |
| | | |
| | | if ($res === false) { |
| | | @fclose($this->fp); |
| | |
| | | * |
| | | * @return int|bool Number of bytes sent, False on error |
| | | */ |
| | | function putLineC($string, $endln=true, $anonymized=false) |
| | | protected function putLineC($string, $endln=true, $anonymized=false) |
| | | { |
| | | if (!$this->fp) { |
| | | return false; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | return $res; |
| | | } |
| | | |
| | |
| | | * |
| | | * @return string Line of text response |
| | | */ |
| | | function readLine($size = 1024) |
| | | protected function readLine($size = 1024) |
| | | { |
| | | $line = ''; |
| | | |
| | |
| | | |
| | | do { |
| | | if ($this->eof()) { |
| | | return $line ? $line : null; |
| | | return $line ?: null; |
| | | } |
| | | |
| | | $buffer = fgets($this->fp, $size); |
| | |
| | | } |
| | | |
| | | $line .= $buffer; |
| | | } while (substr($buffer, -1) != "\n"); |
| | | } |
| | | while (substr($buffer, -1) != "\n"); |
| | | |
| | | return $line; |
| | | } |
| | |
| | | * |
| | | * @return string Line of text response |
| | | */ |
| | | function multLine($line, $escape = false) |
| | | protected function multLine($line, $escape = false) |
| | | { |
| | | $line = rtrim($line); |
| | | if (preg_match('/\{([0-9]+)\}$/', $line, $m)) { |
| | |
| | | * |
| | | * @return string Response text |
| | | */ |
| | | function readBytes($bytes) |
| | | protected function readBytes($bytes) |
| | | { |
| | | $data = ''; |
| | | $len = 0; |
| | |
| | | * |
| | | * @return string Response text |
| | | */ |
| | | function readReply(&$untagged = null) |
| | | protected function readReply(&$untagged = null) |
| | | { |
| | | do { |
| | | $line = trim($this->readLine(1024)); |
| | |
| | | if ($line[0] == '*') { |
| | | $untagged[] = $line; |
| | | } |
| | | } while ($line[0] == '*'); |
| | | } |
| | | while ($line[0] == '*'); |
| | | |
| | | if ($untagged) { |
| | | $untagged = join("\n", $untagged); |
| | |
| | | * |
| | | * @return int Response status |
| | | */ |
| | | function parseResult($string, $err_prefix = '') |
| | | protected function parseResult($string, $err_prefix = '') |
| | | { |
| | | if (preg_match('/^[a-z0-9*]+ (OK|NO|BAD|BYE)(.*)$/i', trim($string), $matches)) { |
| | | $res = strtoupper($matches[1]); |
| | |
| | | } |
| | | } |
| | | |
| | | return !empty($result) ? $result : false; |
| | | return $result ?: false; |
| | | } |
| | | |
| | | /** |
| | |
| | | return false; |
| | | } |
| | | |
| | | if (!stream_socket_enable_crypto($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { |
| | | if (isset($this->prefs['socket_options']['ssl']['crypto_method'])) { |
| | | $crypto_method = $this->prefs['socket_options']['ssl']['crypto_method']; |
| | | } |
| | | else { |
| | | // There is no flag to enable all TLS methods. Net_SMTP |
| | | // handles enabling TLS similarly. |
| | | $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT |
| | | | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT |
| | | | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; |
| | | } |
| | | |
| | | if (!stream_socket_enable_crypto($this->fp, true, $crypto_method)) { |
| | | $this->setError(self::ERROR_BAD, "Unable to negotiate TLS"); |
| | | $this->closeConnection(); |
| | | return false; |
| | |
| | | */ |
| | | public function connected() |
| | | { |
| | | return ($this->fp && $this->logged) ? true : false; |
| | | return $this->fp && $this->logged; |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | $response = explode("\r\n", $response); |
| | | foreach ($response as $line) { |
| | | if (preg_match('/^\* ([0-9]+) (EXISTS|RECENT)$/i', $line, $m)) { |
| | | $this->data[strtoupper($m[2])] = (int) $m[1]; |
| | | } |
| | | else if (preg_match('/^\* OK \[/i', $line, $match)) { |
| | | $line = substr($line, 6); |
| | | if (preg_match('/^(UIDNEXT|UIDVALIDITY|UNSEEN) ([0-9]+)/i', $line, $match)) { |
| | | $this->data[strtoupper($match[1])] = (int) $match[2]; |
| | | } |
| | | else if (preg_match('/^(HIGHESTMODSEQ) ([0-9]+)/i', $line, $match)) { |
| | | $this->data[strtoupper($match[1])] = (string) $match[2]; |
| | | } |
| | | else if (preg_match('/^(NOMODSEQ)/i', $line, $match)) { |
| | | $this->data[strtoupper($match[1])] = true; |
| | | } |
| | | else if (preg_match('/^PERMANENTFLAGS \(([^\)]+)\)/iU', $line, $match)) { |
| | | $this->data['PERMANENTFLAGS'] = explode(' ', $match[1]); |
| | | if (preg_match('/^\* OK \[/i', $line)) { |
| | | $pos = strcspn($line, ' ]', 6); |
| | | $token = strtoupper(substr($line, 6, $pos)); |
| | | $pos += 7; |
| | | |
| | | switch ($token) { |
| | | case 'UIDNEXT': |
| | | case 'UIDVALIDITY': |
| | | case 'UNSEEN': |
| | | if ($len = strspn($line, '0123456789', $pos)) { |
| | | $this->data[$token] = (int) substr($line, $pos, $len); |
| | | } |
| | | break; |
| | | |
| | | case 'HIGHESTMODSEQ': |
| | | if ($len = strspn($line, '0123456789', $pos)) { |
| | | $this->data[$token] = (string) substr($line, $pos, $len); |
| | | } |
| | | break; |
| | | |
| | | case 'NOMODSEQ': |
| | | $this->data[$token] = true; |
| | | break; |
| | | |
| | | case 'PERMANENTFLAGS': |
| | | $start = strpos($line, '(', $pos); |
| | | $end = strrpos($line, ')'); |
| | | if ($start && $end) { |
| | | $flags = substr($line, $start + 1, $end - $start - 1); |
| | | $this->data[$token] = explode(' ', $flags); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | // QRESYNC FETCH response (RFC5162) |
| | | else if (preg_match('/^\* ([0-9+]) FETCH/i', $line, $match)) { |
| | | $line = substr($line, strlen($match[0])); |
| | | $fetch_data = $this->tokenizeResponse($line, 1); |
| | | $data = array('id' => $match[1]); |
| | | else if (preg_match('/^\* ([0-9]+) (EXISTS|RECENT|FETCH)/i', $line, $match)) { |
| | | $token = strtoupper($match[2]); |
| | | switch ($token) { |
| | | case 'EXISTS': |
| | | case 'RECENT': |
| | | $this->data[$token] = (int) $match[1]; |
| | | break; |
| | | |
| | | for ($i=0, $size=count($fetch_data); $i<$size; $i+=2) { |
| | | $data[strtolower($fetch_data[$i])] = $fetch_data[$i+1]; |
| | | case 'FETCH': |
| | | // QRESYNC FETCH response (RFC5162) |
| | | $line = substr($line, strlen($match[0])); |
| | | $fetch_data = $this->tokenizeResponse($line, 1); |
| | | $data = array('id' => $match[1]); |
| | | |
| | | for ($i=0, $size=count($fetch_data); $i<$size; $i+=2) { |
| | | $data[strtolower($fetch_data[$i])] = $fetch_data[$i+1]; |
| | | } |
| | | |
| | | $this->data['QRESYNC'][$data['uid']] = $data; |
| | | break; |
| | | } |
| | | |
| | | $this->data['QRESYNC'][$data['uid']] = $data; |
| | | } |
| | | // QRESYNC VANISHED response (RFC5162) |
| | | else if (preg_match('/^\* VANISHED [()EARLIER]*/i', $line, $match)) { |
| | |
| | | list($code, $response) = $this->execute('STATUS', array($this->escape($mailbox), |
| | | '(' . implode(' ', (array) $items) . ')')); |
| | | |
| | | if ($code == self::ERROR_OK && preg_match('/\* STATUS /i', $response)) { |
| | | if ($code == self::ERROR_OK && preg_match('/^\* STATUS /i', $response)) { |
| | | $result = array(); |
| | | $response = substr($response, 9); // remove prefix "* STATUS " |
| | | |
| | |
| | | !empty($args) ? '(' . implode(' ', (array) $args) . ')' : $this->escape(null) |
| | | )); |
| | | |
| | | if ($code == self::ERROR_OK && preg_match('/\* ID /i', $response)) { |
| | | if ($code == self::ERROR_OK && preg_match('/^\* ID /i', $response)) { |
| | | $response = substr($response, 5); // remove prefix "* ID " |
| | | $items = $this->tokenizeResponse($response, 1); |
| | | $result = null; |
| | |
| | | |
| | | list($code, $response) = $this->execute('ENABLE', $extension); |
| | | |
| | | if ($code == self::ERROR_OK && preg_match('/\* ENABLED /i', $response)) { |
| | | if ($code == self::ERROR_OK && preg_match('/^\* ENABLED /i', $response)) { |
| | | $response = substr($response, 10); // remove prefix "* ENABLED " |
| | | $result = (array) $this->tokenizeResponse($response); |
| | | |
| | |
| | | while (preg_match('/^BODY\[([0-9\.]+)\.'.$type.'\]/', $line, $matches)) { |
| | | $line = substr($line, strlen($matches[0])); |
| | | $result[$matches[1]] = trim($this->multLine($line)); |
| | | $line = ltrim($this->readLine(1024)); |
| | | $line = $this->readLine(1024); |
| | | } |
| | | } |
| | | } |
| | |
| | | if (!is_array($entries)) { |
| | | $entries = array($entries); |
| | | } |
| | | |
| | | // create entries string |
| | | // ANNOTATEMORE drafts before version 08 require quoted parameters |
| | | foreach ($entries as $idx => $name) { |
| | |
| | | if (!is_array($attribs)) { |
| | | $attribs = array($attribs); |
| | | } |
| | | // create entries string |
| | | |
| | | // create attributes string |
| | | foreach ($attribs as $idx => $name) { |
| | | $attribs[$idx] = $this->escape($name, true); |
| | | } |
| | |
| | | if (!is_numeric(($bytes = substr($str, 1, $epos - 1)))) { |
| | | // error |
| | | } |
| | | |
| | | $result[] = $bytes ? substr($str, $epos + 3, $bytes) : ''; |
| | | // Advance the string |
| | | $str = substr($str, $epos + 3 + $bytes); |
| | | $str = substr($str, $epos + 3 + $bytes); |
| | | break; |
| | | |
| | | // Quoted string |
| | |
| | | } |
| | | } |
| | | } |
| | | if ($str[$pos] != '"') { |
| | | // error |
| | | } |
| | | |
| | | // we need to strip slashes for a quoted string |
| | | $result[] = stripslashes(substr($str, 1, $pos - 1)); |
| | | $str = substr($str, $pos + 1); |
| | |
| | | |
| | | // Parenthesized list |
| | | case '(': |
| | | $str = substr($str, 1); |
| | | $str = substr($str, 1); |
| | | $result[] = self::tokenizeResponse($str); |
| | | break; |
| | | |
| | | case ')': |
| | | $str = substr($str, 1); |
| | | return $result; |
| | | break; |
| | | |
| | | // String atom, number, astring, NIL, *, % |
| | | default: |
| | |
| | | // we do not exclude [ and ] (#1489223) |
| | | if (preg_match('/^([^\x00-\x20\x29\x7F]+)/', $str, $m)) { |
| | | $result[] = $m[1] == 'NIL' ? null : $m[1]; |
| | | $str = substr($str, strlen($m[1])); |
| | | $str = substr($str, strlen($m[1])); |
| | | } |
| | | break; |
| | | } |