| | |
| | | break; |
| | | } |
| | | if (!empty($this->prefs['debug_mode'])) { |
| | | write_log('imap', 'S: '. chop($buffer)); |
| | | write_log('imap', 'S: '. rtrim($buffer)); |
| | | } |
| | | $line .= $buffer; |
| | | } while ($buffer[strlen($buffer)-1] != "\n"); |
| | |
| | | |
| | | private function multLine($line, $escape=false) |
| | | { |
| | | $line = chop($line); |
| | | $line = rtrim($line); |
| | | if (preg_match('/\{[0-9]+\}$/', $line)) { |
| | | $out = ''; |
| | | |
| | |
| | | } |
| | | |
| | | // don't use it in loops, until you exactly know what you're doing |
| | | private function readReply($untagged=null) |
| | | private function readReply(&$untagged=null) |
| | | { |
| | | do { |
| | | $line = trim($this->readLine(1024)); |
| | |
| | | $host = $this->prefs['ssl_mode'] . '://' . $host; |
| | | } |
| | | |
| | | $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr, 10); |
| | | // Connect |
| | | if ($this->prefs['timeout'] > 0) |
| | | $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr, $this->prefs['timeout']); |
| | | else |
| | | $this->fp = @fsockopen($host, $this->prefs['port'], $errno, $errstr); |
| | | |
| | | if (!$this->fp) { |
| | | $this->error = sprintf("Could not connect to %s:%d: %s", $host, $this->prefs['port'], $errstr); |
| | | $this->errornum = -2; |
| | | return false; |
| | | } |
| | | |
| | | stream_set_timeout($this->fp, 10); |
| | | if ($this->prefs['timeout'] > 0) |
| | | stream_set_timeout($this->fp, $this->prefs['timeout']); |
| | | |
| | | $line = trim(fgets($this->fp, 8192)); |
| | | |
| | | if ($this->prefs['debug_mode'] && $line) { |
| | |
| | | } |
| | | $this->getNamespace(); |
| | | $this->logged = true; |
| | | |
| | | return true; |
| | | } else { |
| | | return false; |
| | |
| | | |
| | | if ($this->putLine("sel1 SELECT \"".$this->escape($mailbox).'"')) { |
| | | do { |
| | | $line = chop($this->readLine(300)); |
| | | $a = explode(' ', $line); |
| | | if (count($a) == 3) { |
| | | $token = strtoupper($a[2]); |
| | | if ($token == 'EXISTS') { |
| | | $this->exists = (int) $a[1]; |
| | | } |
| | | else if ($token == 'RECENT') { |
| | | $this->recent = (int) $a[1]; |
| | | } |
| | | $line = rtrim($this->readLine(512)); |
| | | |
| | | if (preg_match('/^\* ([0-9]+) (EXISTS|RECENT)$/', $line, $m)) { |
| | | $token = strtolower($m[2]); |
| | | $this->$token = (int) $m[1]; |
| | | } |
| | | else if (preg_match('/\[?PERMANENTFLAGS\s+\(([^\)]+)\)\]/U', $line, $match)) { |
| | | $this->permanentflags = explode(' ', $match[1]); |
| | | } |
| | | } while (!$this->startsWith($line, 'sel1', true, true)); |
| | | |
| | | if (strcasecmp($a[1], 'OK') == 0) { |
| | | if ($this->parseResult($line) == 0) { |
| | | $this->selected = $mailbox; |
| | | return true; |
| | | } |
| | | else { |
| | | $this->error = "Couldn't select $mailbox"; |
| | | } |
| | | } |
| | | |
| | | $this->error = "Couldn't select $mailbox"; |
| | | return false; |
| | | } |
| | | |
| | |
| | | return false; |
| | | } |
| | | do { |
| | | $line = chop($this->readLine()); |
| | | $line = rtrim($this->readLine()); |
| | | if ($this->startsWith($line, '* SORT')) { |
| | | $data .= substr($line, 7); |
| | | } else if (preg_match('/^[0-9 ]+$/', $line)) { |
| | |
| | | } while (!$this->startsWith($line, 's ', true, true)); |
| | | |
| | | $result_code = $this->parseResult($line); |
| | | |
| | | if ($result_code != 0) { |
| | | $this->error = "Sort: $line"; |
| | | return false; |
| | |
| | | $result = array(); |
| | | |
| | | do { |
| | | $line = chop($this->readLine(200)); |
| | | $line = rtrim($this->readLine(200)); |
| | | $line = $this->multLine($line); |
| | | |
| | | if (preg_match('/^\* ([0-9]+) FETCH/', $line, $m)) { |
| | |
| | | $result = -1; |
| | | if ($this->putLine("fuid FETCH $id (UID)")) { |
| | | do { |
| | | $line = chop($this->readLine(1024)); |
| | | $line = rtrim($this->readLine(1024)); |
| | | if (preg_match("/^\* $id FETCH \(UID (.*)\)/i", $line, $r)) { |
| | | $result = $r[1]; |
| | | } |
| | |
| | | if (!$line) |
| | | break; |
| | | |
| | | $a = explode(' ', $line); |
| | | |
| | | if (($line[0] == '*') && ($a[2] == 'FETCH')) { |
| | | $id = $a[1]; |
| | | if (preg_match('/^\* ([0-9]+) FETCH/', $line, $m)) { |
| | | $id = $m[1]; |
| | | |
| | | $result[$id] = new rcube_mail_header; |
| | | $result[$id]->id = $id; |
| | |
| | | // to the next valid header line. |
| | | |
| | | do { |
| | | $line = chop($this->readLine(300), "\r\n"); |
| | | $line = rtrim($this->readLine(300), "\r\n"); |
| | | |
| | | // The preg_match below works around communigate imap, which outputs " UID <number>)". |
| | | // Without this, the while statement continues on and gets the "FH0 OK completed" message. |
| | |
| | | } |
| | | break; |
| | | case 'in-reply-to': |
| | | $result[$id]->in_reply_to = preg_replace('/[\n<>]/', '', $string); |
| | | $result[$id]->in_reply_to = str_replace(array("\n", '<', '>'), '', $string); |
| | | break; |
| | | case 'references': |
| | | $result[$id]->references = $string; |
| | |
| | | break; |
| | | } // end switch () |
| | | } // end while () |
| | | } else { |
| | | $a = explode(' ', $line); |
| | | } |
| | | |
| | | // process flags |
| | |
| | | $flags_a = explode(' ', $flags_str); |
| | | |
| | | if (is_array($flags_a)) { |
| | | // reset($flags_a); |
| | | foreach($flags_a as $flag) { |
| | | $flag = strtoupper($flag); |
| | | if ($flag == 'SEEN') { |
| | |
| | | } |
| | | |
| | | do { |
| | | $line = $this->readLine(1000); |
| | | $line = $this->readLine(); |
| | | if ($line[0] == '*') { |
| | | $c++; |
| | | } |
| | |
| | | { |
| | | $node = array(); |
| | | if ($str[$begin] != '(') { |
| | | $stop = $begin + strspn($str, "1234567890", $begin, $end - $begin); |
| | | $stop = $begin + strspn($str, '1234567890', $begin, $end - $begin); |
| | | $msg = substr($str, $begin, $stop - $begin); |
| | | if ($msg == 0) |
| | | return $node; |
| | |
| | | |
| | | function thread($folder, $algorithm='REFERENCES', $criteria='', $encoding='US-ASCII') |
| | | { |
| | | $old_sel = $this->selected; |
| | | |
| | | if (!$this->select($folder)) { |
| | | return false; |
| | | return false; |
| | | } |
| | | |
| | | // return empty result when folder is empty and we're just after SELECT |
| | | if ($old_sel != $folder && !$this->exists) { |
| | | return array(array(), array(), array()); |
| | | } |
| | | |
| | | $encoding = $encoding ? trim($encoding) : 'US-ASCII'; |
| | | $algorithm = $algorithm ? trim($algorithm) : 'REFERENCES'; |
| | | $criteria = $criteria ? 'ALL '.trim($criteria) : 'ALL'; |
| | | $data = ''; |
| | | |
| | | if (!$this->putLineC("thrd1 THREAD $algorithm $encoding $criteria")) { |
| | | return false; |
| | | } |
| | | do { |
| | | $line = trim($this->readLine(10000)); |
| | | if (preg_match('/^\* THREAD/', $line)) { |
| | | $str = trim(substr($line, 8)); |
| | | $depthmap = array(); |
| | | $haschildren = array(); |
| | | $tree = $this->parseThread($str, 0, strlen($str), null, null, 0, $depthmap, $haschildren); |
| | | $line = trim($this->readLine()); |
| | | if ($this->startsWith($line, '* THREAD')) { |
| | | $data .= substr($line, 9); |
| | | } else if (preg_match('/^[0-9() ]+$/', $line)) { |
| | | $data .= $line; |
| | | } |
| | | } while (!$this->startsWith($line, 'thrd1', true, true)); |
| | | |
| | | $result_code = $this->parseResult($line); |
| | | if ($result_code == 0) { |
| | | return array($tree, $depthmap, $haschildren); |
| | | $depthmap = array(); |
| | | $haschildren = array(); |
| | | $tree = $this->parseThread($data, 0, strlen($data), null, null, 0, $depthmap, $haschildren); |
| | | return array($tree, $depthmap, $haschildren); |
| | | } |
| | | |
| | | $this->error = "Thread: $line"; |
| | |
| | | |
| | | function search($folder, $criteria, $return_uid=false) |
| | | { |
| | | $old_sel = $this->selected; |
| | | |
| | | if (!$this->select($folder)) { |
| | | return false; |
| | | } |
| | | |
| | | // return empty result when folder is empty and we're just after SELECT |
| | | if ($old_sel != $folder && !$this->exists) { |
| | | return array(); |
| | | } |
| | | |
| | | $data = ''; |
| | | $query = 'srch1 ' . ($return_uid ? 'UID ' : '') . 'SEARCH ' . chop($criteria); |
| | | $query = 'srch1 ' . ($return_uid ? 'UID ' : '') . 'SEARCH ' . trim($criteria); |
| | | |
| | | if (!$this->putLineC($query)) { |
| | | return false; |
| | |
| | | $command = 'LIST'; |
| | | } |
| | | |
| | | $ref = $this->escape($ref); |
| | | $mailbox = $this->escape($mailbox); |
| | | |
| | | // send command |
| | | if (!$this->putLine($key." ".$command." \"". $this->escape($ref) ."\" \"". $this->escape($mailbox) ."\"")) { |
| | | if (!$this->putLine($key." ".$command." \"". $ref ."\" \"". $mailbox ."\"")) { |
| | | $this->error = "Couldn't send $command command"; |
| | | return false; |
| | | } |
| | |
| | | do { |
| | | $line = $this->readLine(500); |
| | | $line = $this->multLine($line, true); |
| | | $a = explode(' ', $line); |
| | | $line = trim($line); |
| | | |
| | | if (($line[0] == '*') && ($a[1] == $command)) { |
| | | $line = rtrim($line); |
| | | // split one line |
| | | $a = rcube_explode_quoted_string(' ', $line); |
| | | // last string is folder name |
| | | $folders[] = preg_replace(array('/^"/', '/"$/'), '', $this->unEscape($a[count($a)-1])); |
| | | // second from last is delimiter |
| | | $delim = trim($a[count($a)-2], '"'); |
| | | if (preg_match('/^\* '.$command.' \(([^\)]*)\) "*([^"]+)"* (.*)$/', $line, $m)) { |
| | | // folder name |
| | | $folders[] = preg_replace(array('/^"/', '/"$/'), '', $this->unEscape($m[3])); |
| | | // attributes |
| | | // $attrib = explode(' ', $m[1]); |
| | | // delimiter |
| | | // $delim = $m[2]; |
| | | } |
| | | } while (!$this->startsWith($line, $key, true)); |
| | | |
| | |
| | | } |
| | | |
| | | do { |
| | | $line = $this->readLine(1000); |
| | | $line = $this->readLine(1024); |
| | | $line = $this->multLine($line); |
| | | |
| | | if (preg_match('/BODY\[([0-9\.]+)\.'.$type.'\]/', $line, $matches)) { |
| | |
| | | $mode = 0; |
| | | } |
| | | |
| | | $reply_key = '* ' . $id; |
| | | $result = false; |
| | | |
| | | // format request |
| | | $key = 'ftch0'; |
| | | $request = $key . ($is_uid ? ' UID' : '') . " FETCH $id (BODY.PEEK[$part])"; |
| | | $reply_key = '* ' . $id; |
| | | $key = 'ftch0'; |
| | | $request = $key . ($is_uid ? ' UID' : '') . " FETCH $id (BODY.PEEK[$part])"; |
| | | |
| | | // send request |
| | | if (!$this->putLine($request)) { |
| | | return false; |
| | |
| | | |
| | | // receive reply line |
| | | do { |
| | | $line = chop($this->readLine(1000)); |
| | | $line = rtrim($this->readLine(1024)); |
| | | $a = explode(' ', $line); |
| | | } while (!($end = $this->startsWith($line, $key, true)) && $a[2] != 'FETCH'); |
| | | |
| | | $len = strlen($line); |
| | | $len = strlen($line); |
| | | $result = false; |
| | | |
| | | // handle empty "* X FETCH ()" response |
| | | if ($line[$len-1] == ')' && $line[$len-2] != '(') { |
| | |
| | | $line = $this->readLine(1024); |
| | | } while (!$this->startsWith($line, $key, true)); |
| | | |
| | | if ($result) { |
| | | if ($result !== false) { |
| | | if ($file) { |
| | | fwrite($file, $result); |
| | | } else if ($print) { |
| | |
| | | return false; |
| | | } |
| | | |
| | | function appendFromFile($folder, $path, $headers=null, $separator="\n\n") |
| | | function appendFromFile($folder, $path, $headers=null) |
| | | { |
| | | if (!$folder) { |
| | | return false; |
| | |
| | | return false; |
| | | } |
| | | |
| | | $body_separator = "\r\n\r\n"; |
| | | $len = filesize($path); |
| | | |
| | | if (!$len) { |
| | | return false; |
| | | } |
| | | |
| | | if ($headers) { |
| | | $headers = preg_replace('/[\r\n]+$/', '', $headers); |
| | | $len += strlen($headers) + strlen($separator); |
| | | $len += strlen($headers) + strlen($body_separator); |
| | | } |
| | | |
| | | // send APPEND command |
| | |
| | | |
| | | // send headers with body separator |
| | | if ($headers) { |
| | | $this->putLine($headers . $separator, false); |
| | | $this->putLine($headers . $body_separator, false); |
| | | } |
| | | |
| | | // send file |
| | |
| | | // get line(s) containing quota info |
| | | if ($this->putLine('QUOT1 GETQUOTAROOT "INBOX"')) { |
| | | do { |
| | | $line = chop($this->readLine(5000)); |
| | | $line = rtrim($this->readLine(5000)); |
| | | if ($this->startsWith($line, '* QUOTA ')) { |
| | | $quota_lines[] = $line; |
| | | } |
| | |
| | | // return false if not found, parse if found |
| | | $min_free = PHP_INT_MAX; |
| | | foreach ($quota_lines as $key => $quota_line) { |
| | | $quota_line = preg_replace('/[()]/', '', $quota_line); |
| | | $quota_line = str_replace(array('(', ')'), '', $quota_line); |
| | | $parts = explode(' ', $quota_line); |
| | | $storage_part = array_search('STORAGE', $parts); |
| | | |
| | |
| | | |
| | | } |
| | | |
| | | ?> |