| | |
| | | +-----------------------------------------------------------------------+ |
| | | | program/include/rcube_imap_generic.php | |
| | | | | |
| | | | This file is part of the RoundCube Webmail client | |
| | | | Copyright (C) 2005-2010, RoundCube Dev. - Switzerland | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2010, Roundcube Dev. - Switzerland | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | PURPOSE: | |
| | |
| | | { |
| | | } |
| | | |
| | | private function putLine($string, $endln=true) |
| | | function putLine($string, $endln=true) |
| | | { |
| | | if (!$this->fp) |
| | | return false; |
| | |
| | | write_log('imap', 'C: '. rtrim($string)); |
| | | } |
| | | |
| | | return fputs($this->fp, $string . ($endln ? "\r\n" : '')); |
| | | $res = fwrite($this->fp, $string . ($endln ? "\r\n" : '')); |
| | | |
| | | if ($res === false) { |
| | | @fclose($this->fp); |
| | | $this->fp = null; |
| | | } |
| | | |
| | | return $res; |
| | | } |
| | | |
| | | // $this->putLine replacement with Command Continuation Requests (RFC3501 7.5) support |
| | | private function putLineC($string, $endln=true) |
| | | function putLineC($string, $endln=true) |
| | | { |
| | | if (!$this->fp) |
| | | return false; |
| | |
| | | return $res; |
| | | } |
| | | |
| | | private function readLine($size=1024) |
| | | function readLine($size=1024) |
| | | { |
| | | $line = ''; |
| | | |
| | |
| | | return $line; |
| | | } |
| | | |
| | | private function multLine($line, $escape=false) |
| | | function multLine($line, $escape=false) |
| | | { |
| | | $line = rtrim($line); |
| | | if (preg_match('/\{[0-9]+\}$/', $line)) { |
| | |
| | | return $line; |
| | | } |
| | | |
| | | private function readBytes($bytes) |
| | | function readBytes($bytes) |
| | | { |
| | | $data = ''; |
| | | $len = 0; |
| | |
| | | } |
| | | |
| | | // don't use it in loops, until you exactly know what you're doing |
| | | private function readReply(&$untagged=null) |
| | | function readReply(&$untagged=null) |
| | | { |
| | | do { |
| | | $line = trim($this->readLine(1024)); |
| | |
| | | return $line; |
| | | } |
| | | |
| | | private function parseResult($string) |
| | | function parseResult($string) |
| | | { |
| | | $a = explode(' ', trim($string)); |
| | | if (count($a) >= 2) { |
| | |
| | | } |
| | | |
| | | // check if $string starts with $match (or * BYE/BAD) |
| | | private function startsWith($string, $match, $error=false, $nonempty=false) |
| | | function startsWith($string, $match, $error=false, $nonempty=false) |
| | | { |
| | | $len = strlen($match); |
| | | if ($len == 0) { |
| | |
| | | return true; |
| | | } |
| | | if (strncmp($string, $match, $len) == 0) { |
| | | return true; |
| | | } |
| | | if ($error && preg_match('/^\* (BYE|BAD) /i', $string, $m)) { |
| | | if (strtoupper($m[1]) == 'BYE') { |
| | | @fclose($this->fp); |
| | | $this->fp = null; |
| | | } |
| | | return true; |
| | | } |
| | | if ($nonempty && !strlen($string)) { |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private function startsWithI($string, $match, $error=false, $nonempty=false) |
| | | { |
| | | $len = strlen($match); |
| | | if ($len == 0) { |
| | | return false; |
| | | } |
| | | if (!$this->fp) { |
| | | return true; |
| | | } |
| | | if (strncasecmp($string, $match, $len) == 0) { |
| | | return true; |
| | | } |
| | | if ($error && preg_match('/^\* (BYE|BAD) /i', $string, $m)) { |
| | |
| | | } |
| | | do { |
| | | $line = trim($this->readLine(1024)); |
| | | $a = explode(' ', $line); |
| | | if ($line[0] == '*') { |
| | | while (list($k, $w) = each($a)) { |
| | | if ($w != '*' && $w != 'CAPABILITY') |
| | | $this->capability[] = strtoupper($w); |
| | | } |
| | | } |
| | | } while ($a[0] != 'cp01'); |
| | | if (preg_match('/^\* CAPABILITY (.+)/i', $line, $matches)) { |
| | | $this->capability = explode(' ', strtoupper($matches[1])); |
| | | } |
| | | } while (!$this->startsWith($line, 'cp01', true)); |
| | | |
| | | $this->capability_readed = true; |
| | | |
| | |
| | | return true; |
| | | } |
| | | |
| | | if (!$this->getCapability('NAMESPACE')) { |
| | | return false; |
| | | } |
| | | |
| | | if (!$this->putLine("ns1 NAMESPACE")) { |
| | | return false; |
| | | } |
| | | do { |
| | | $line = $this->readLine(1024); |
| | | if ($this->startsWith($line, '* NAMESPACE')) { |
| | | $i = 0; |
| | | $line = $this->unEscape($line); |
| | | $data = $this->parseNamespace(substr($line,11), $i, 0, 0); |
| | | } |
| | | } while (!$this->startsWith($line, 'ns1', true, true)); |
| | | |
| | | if (!is_array($data)) { |
| | | if (!is_array($data = $this->_namespace())) { |
| | | return false; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | do { |
| | | $line = $this->readLine(500); |
| | | if ($line[0] == '*') { |
| | | $line = rtrim($line); |
| | | $a = rcube_explode_quoted_string(' ', $this->unEscape($line)); |
| | | if ($a[0] == '*') { |
| | | $delimiter = str_replace('"', '', $a[count($a)-2]); |
| | | } |
| | | $line = $this->readLine(1024); |
| | | if (preg_match('/^\* LIST \([^\)]*\) "*([^"]+)"* ""/', $line, $m)) { |
| | | $delimiter = $this->unEscape($m[1]); |
| | | } |
| | | } while (!$this->startsWith($line, 'ghd', true, true)); |
| | | |
| | |
| | | |
| | | // if that fails, try namespace extension |
| | | // try to fetch namespace data |
| | | if (!$this->putLine("ns1 NAMESPACE")) { |
| | | if (!is_array($data = $this->_namespace())) { |
| | | return false; |
| | | } |
| | | |
| | | do { |
| | | $line = $this->readLine(1024); |
| | | if ($this->startsWith($line, '* NAMESPACE')) { |
| | | $i = 0; |
| | | $line = $this->unEscape($line); |
| | | $data = $this->parseNamespace(substr($line,11), $i, 0, 0); |
| | | } |
| | | } while (!$this->startsWith($line, 'ns1', true, true)); |
| | | |
| | | if (!is_array($data)) { |
| | | return false; |
| | | } |
| | | |
| | | // extract user space data (opposed to global/shared space) |
| | | $user_space_data = $data[0]; |
| | |
| | | $delimiter = $first_userspace[1]; |
| | | |
| | | return $delimiter; |
| | | } |
| | | |
| | | function _namespace() |
| | | { |
| | | if (!$this->getCapability('NAMESPACE')) { |
| | | return false; |
| | | } |
| | | |
| | | if (!$this->putLine("ns1 NAMESPACE")) { |
| | | return false; |
| | | } |
| | | |
| | | do { |
| | | $line = $this->readLine(1024); |
| | | if (preg_match('/^\* NAMESPACE/', $line)) { |
| | | $i = 0; |
| | | $data = $this->parseNamespace(substr($line,11), $i, 0, 0); |
| | | } |
| | | } while (!$this->startsWith($line, 'ns1', true, true)); |
| | | |
| | | if (!is_array($data)) { |
| | | return false; |
| | | } |
| | | |
| | | return $data; |
| | | } |
| | | |
| | | function connect($host, $user, $password, $options=null) |
| | |
| | | $this->putLine("tls0 STARTTLS"); |
| | | |
| | | $line = $this->readLine(4096); |
| | | if (!$this->startsWith($line, "tls0 OK")) { |
| | | if (!preg_match('/^tls0 OK/', $line)) { |
| | | $this->error = "Server responded to STARTTLS with: $line"; |
| | | $this->errornum = -2; |
| | | return false; |
| | |
| | | |
| | | function close() |
| | | { |
| | | if ($this->putLine("I LOGOUT")) { |
| | | if ($this->logged && $this->putLine("I LOGOUT")) { |
| | | if (!feof($this->fp)) |
| | | fgets($this->fp, 1024); |
| | | } |
| | |
| | | $add = $this->compressMessageSet(join(',', $add)); |
| | | |
| | | $command = "s ".$is_uid."SORT ($field) $encoding ALL"; |
| | | $line = $data = ''; |
| | | $line = ''; |
| | | $data = ''; |
| | | |
| | | if (!empty($add)) |
| | | $command .= ' '.$add; |
| | |
| | | } |
| | | do { |
| | | $line = rtrim($this->readLine()); |
| | | if ($this->startsWith($line, '* SORT')) { |
| | | if (!$data && preg_match('/^\* SORT/', $line)) { |
| | | $data .= substr($line, 7); |
| | | } else if (preg_match('/^[0-9 ]+$/', $line)) { |
| | | $data .= $line; |
| | |
| | | } |
| | | do { |
| | | $line = trim($this->readLine()); |
| | | if ($this->startsWith($line, '* THREAD')) { |
| | | if (!$data && preg_match('/^\* THREAD/', $line)) { |
| | | $data .= substr($line, 9); |
| | | } else if (preg_match('/^[0-9() ]+$/', $line)) { |
| | | $data .= $line; |
| | |
| | | |
| | | do { |
| | | $line = trim($this->readLine()); |
| | | if ($this->startsWith($line, '* SEARCH')) { |
| | | if (!$data && preg_match('/^\* SEARCH/', $line)) { |
| | | $data .= substr($line, 8); |
| | | } else if (preg_match('/^[0-9 ]+$/', $line)) { |
| | | $data .= $line; |
| | |
| | | // folder name |
| | | $folders[] = preg_replace(array('/^"/', '/"$/'), '', $this->unEscape($m[3])); |
| | | // attributes |
| | | // $attrib = explode(' ', $m[1]); |
| | | // $attrib = explode(' ', $this->unEscape($m[1])); |
| | | // delimiter |
| | | // $delim = $m[2]; |
| | | // $delim = $this->unEscape($m[2]); |
| | | } |
| | | } while (!$this->startsWith($line, $key, true)); |
| | | |
| | |
| | | |
| | | while ($bytes > 0) { |
| | | $line = $this->readLine(1024); |
| | | |
| | | if ($line === NULL) |
| | | break; |
| | | |
| | | $len = strlen($line); |
| | | |
| | | if ($len > $bytes) { |
| | |
| | | if ($this->putLine('QUOT1 GETQUOTAROOT "INBOX"')) { |
| | | do { |
| | | $line = rtrim($this->readLine(5000)); |
| | | if ($this->startsWith($line, '* QUOTA ')) { |
| | | if (preg_match('/^\* QUOTA /', $line)) { |
| | | $quota_lines[] = $line; |
| | | } |
| | | } while (!$this->startsWith($line, 'QUOT1', true, true)); |
| | |
| | | $in_quotes = false; |
| | | $elem = 0; |
| | | |
| | | for ($i;$i<$len;$i++) { |
| | | for ($i; $i<$len; $i++) { |
| | | $c = (string)$str[$i]; |
| | | if ($c == '(' && !$in_quotes) { |
| | | $i++; |
| | |
| | | } else if ($c == '\\') { |
| | | $i++; |
| | | if ($in_quotes) { |
| | | $data[$elem] .= $c.$str[$i]; |
| | | $data[$elem] .= $str[$i]; |
| | | } |
| | | } else if ($c == '"') { |
| | | $in_quotes = !$in_quotes; |