- Parse untagged CAPABILITY response for LOGIN command (#1486742)

release-0.6
alecpl 15 years ago
parent 30aa4ccaaf
commit 1d51658ba5

@ -1,6 +1,7 @@
CHANGELOG RoundCube Webmail CHANGELOG RoundCube Webmail
=========================== ===========================
- Parse untagged CAPABILITY response for LOGIN command (#1486742)
- Renamed all php-cli scripts to use .sh extension - Renamed all php-cli scripts to use .sh extension
- Some files from /bin + spellchecking actions moved to the new 'utils' task - Some files from /bin + spellchecking actions moved to the new 'utils' task
- Added thread tree icons - Added thread tree icons

@ -30,7 +30,7 @@
* Struct representing an e-mail message header * Struct representing an e-mail message header
* *
* @package Mail * @package Mail
* @author Aleksander Machniak <alec@alec.pl> * @author Aleksander Machniak <alec@alec.pl>
*/ */
class rcube_mail_header class rcube_mail_header
{ {
@ -80,7 +80,7 @@ class iilBasicHeader extends rcube_mail_header
* PHP based wrapper class to connect to an IMAP server * PHP based wrapper class to connect to an IMAP server
* *
* @package Mail * @package Mail
* @author Aleksander Machniak <alec@alec.pl> * @author Aleksander Machniak <alec@alec.pl>
*/ */
class rcube_imap_generic class rcube_imap_generic
{ {
@ -118,7 +118,7 @@ class rcube_imap_generic
function __construct() function __construct()
{ {
} }
private function putLine($string, $endln=true) private function putLine($string, $endln=true)
{ {
if (!$this->fp) if (!$this->fp)
@ -127,7 +127,7 @@ class rcube_imap_generic
if (!empty($this->prefs['debug_mode'])) { if (!empty($this->prefs['debug_mode'])) {
write_log('imap', 'C: '. rtrim($string)); write_log('imap', 'C: '. rtrim($string));
} }
return fputs($this->fp, $string . ($endln ? "\r\n" : '')); return fputs($this->fp, $string . ($endln ? "\r\n" : ''));
} }
@ -173,16 +173,16 @@ class rcube_imap_generic
if (!$this->fp) { if (!$this->fp) {
return NULL; return NULL;
} }
if (!$size) { if (!$size) {
$size = 1024; $size = 1024;
} }
do { do {
if (feof($this->fp)) { if (feof($this->fp)) {
return $line ? $line : NULL; return $line ? $line : NULL;
} }
$buffer = fgets($this->fp, $size); $buffer = fgets($this->fp, $size);
if ($buffer === false) { if ($buffer === false) {
@ -204,11 +204,11 @@ class rcube_imap_generic
$line = chop($line); $line = chop($line);
if (preg_match('/\{[0-9]+\}$/', $line)) { if (preg_match('/\{[0-9]+\}$/', $line)) {
$out = ''; $out = '';
preg_match_all('/(.*)\{([0-9]+)\}$/', $line, $a); preg_match_all('/(.*)\{([0-9]+)\}$/', $line, $a);
$bytes = $a[2][0]; $bytes = $a[2][0];
while (strlen($out) < $bytes) { while (strlen($out) < $bytes) {
$line = $this->readBytes($bytes); $line = $this->readBytes($bytes);
if ($line === NULL) if ($line === NULL)
break; break;
$out .= $line; $out .= $line;
@ -216,7 +216,7 @@ class rcube_imap_generic
$line = $a[1][0] . '"' . ($escape ? $this->Escape($out) : $out) . '"'; $line = $a[1][0] . '"' . ($escape ? $this->Escape($out) : $out) . '"';
} }
return $line; return $line;
} }
@ -237,17 +237,23 @@ class rcube_imap_generic
} }
$len = $data_len; $len = $data_len;
} }
return $data; return $data;
} }
// don't use it in loops, until you exactly know what you're doing // don't use it in loops, until you exactly know what you're doing
private function readReply() private function readReply($untagged=null)
{ {
do { do {
$line = trim($this->readLine(1024)); $line = trim($this->readLine(1024));
// store untagged response lines
if ($line[0] == '*')
$untagged[] = $line;
} while ($line[0] == '*'); } while ($line[0] == '*');
if ($untagged)
$untagged = join("\n", $untagged);
return $line; return $line;
} }
@ -331,7 +337,7 @@ class rcube_imap_generic
return false; return false;
} }
// get capabilities (only once) because initial // get capabilities (only once) because initial
// optional CAPABILITY response may differ // optional CAPABILITY response may differ
$this->capability = array(); $this->capability = array();
@ -348,7 +354,7 @@ class rcube_imap_generic
} }
} }
} while ($a[0] != 'cp01'); } while ($a[0] != 'cp01');
$this->capability_readed = true; $this->capability_readed = true;
if (in_array($name, $this->capability)) { if (in_array($name, $this->capability)) {
@ -368,7 +374,7 @@ class rcube_imap_generic
{ {
$ipad = ''; $ipad = '';
$opad = ''; $opad = '';
// initialize ipad, opad // initialize ipad, opad
for ($i=0; $i<64; $i++) { for ($i=0; $i<64; $i++) {
$ipad .= chr(0x36); $ipad .= chr(0x36);
@ -380,17 +386,17 @@ class rcube_imap_generic
for ($i=0; $i<$padLen; $i++) { for ($i=0; $i<$padLen; $i++) {
$pass .= chr(0); $pass .= chr(0);
} }
// generate hash // generate hash
$hash = md5($this->_xor($pass,$opad) . pack("H*", md5($this->_xor($pass, $ipad) . base64_decode($encChallenge)))); $hash = md5($this->_xor($pass,$opad) . pack("H*", md5($this->_xor($pass, $ipad) . base64_decode($encChallenge))));
// generate reply // generate reply
$reply = base64_encode($user . ' ' . $hash); $reply = base64_encode($user . ' ' . $hash);
// send result, get reply // send result, get reply
$this->putLine($reply); $this->putLine($reply);
$line = $this->readLine(1024); $line = $this->readLine(1024);
// process result // process result
$result = $this->parseResult($line); $result = $this->parseResult($line);
if ($result == 0) { if ($result == 0) {
@ -408,7 +414,12 @@ class rcube_imap_generic
{ {
$this->putLine('a001 LOGIN "'.$this->escape($user).'" "'.$this->escape($password).'"'); $this->putLine('a001 LOGIN "'.$this->escape($user).'" "'.$this->escape($password).'"');
$line = $this->readReply(); $line = $this->readReply($untagged);
// re-set capabilities list if untagged CAPABILITY response provided
if (preg_match('/\* CAPABILITY (.+)/i', $untagged, $matches)) {
$this->capability = explode(' ', strtoupper($matches[1]));
}
// process result // process result
$result = $this->parseResult($line); $result = $this->parseResult($line);
@ -420,7 +431,7 @@ class rcube_imap_generic
@fclose($this->fp); @fclose($this->fp);
$this->fp = false; $this->fp = false;
$this->error = "Authentication for $user failed (LOGIN): $line"; $this->error = "Authentication for $user failed (LOGIN): $line";
$this->errornum = $result; $this->errornum = $result;
@ -433,11 +444,11 @@ class rcube_imap_generic
$this->rootdir = $this->prefs['rootdir']; $this->rootdir = $this->prefs['rootdir'];
return true; return true;
} }
if (!$this->getCapability('NAMESPACE')) { if (!$this->getCapability('NAMESPACE')) {
return false; return false;
} }
if (!$this->putLine("ns1 NAMESPACE")) { if (!$this->putLine("ns1 NAMESPACE")) {
return false; return false;
} }
@ -463,12 +474,12 @@ class rcube_imap_generic
if (count($first_userspace)!=2) { if (count($first_userspace)!=2) {
return false; return false;
} }
$this->rootdir = $first_userspace[0]; $this->rootdir = $first_userspace[0];
$this->delimiter = $first_userspace[1]; $this->delimiter = $first_userspace[1];
$this->prefs['rootdir'] = substr($this->rootdir, 0, -1); $this->prefs['rootdir'] = substr($this->rootdir, 0, -1);
$this->prefs['delimiter'] = $this->delimiter; $this->prefs['delimiter'] = $this->delimiter;
return true; return true;
} }
@ -478,8 +489,8 @@ class rcube_imap_generic
* INBOX.foo -> . * INBOX.foo -> .
* INBOX/foo -> / * INBOX/foo -> /
* INBOX\foo -> \ * INBOX\foo -> \
* *
* @return mixed A delimiter (string), or false. * @return mixed A delimiter (string), or false.
* @see connect() * @see connect()
*/ */
function getHierarchyDelimiter() function getHierarchyDelimiter()
@ -497,7 +508,7 @@ class rcube_imap_generic
if (!$this->putLine('ghd LIST "" ""')) { if (!$this->putLine('ghd LIST "" ""')) {
return false; return false;
} }
do { do {
$line = $this->readLine(500); $line = $this->readLine(500);
if ($line[0] == '*') { if ($line[0] == '*') {
@ -531,7 +542,7 @@ class rcube_imap_generic
if (!is_array($data)) { if (!is_array($data)) {
return false; return false;
} }
// extract user space data (opposed to global/shared space) // extract user space data (opposed to global/shared space)
$user_space_data = $data[0]; $user_space_data = $data[0];
if (!is_array($user_space_data)) { if (!is_array($user_space_data)) {
@ -545,7 +556,7 @@ class rcube_imap_generic
} }
// extract delimiter // extract delimiter
$delimiter = $first_userspace[1]; $delimiter = $first_userspace[1];
return $delimiter; return $delimiter;
} }
@ -566,7 +577,7 @@ class rcube_imap_generic
$message = "INITIAL: $auth_method\n"; $message = "INITIAL: $auth_method\n";
$result = false; $result = false;
// initialize connection // initialize connection
$this->error = ''; $this->error = '';
$this->errornum = 0; $this->errornum = 0;
@ -648,7 +659,7 @@ class rcube_imap_generic
$this->errornum = -2; $this->errornum = -2;
return false; return false;
} }
// Now we're authenticated, capabilities need to be reread // Now we're authenticated, capabilities need to be reread
$this->clearCapability(); $this->clearCapability();
} }
@ -675,18 +686,18 @@ class rcube_imap_generic
if ($line[0] == '+') { if ($line[0] == '+') {
// got a challenge string, try CRAM-MD5 // got a challenge string, try CRAM-MD5
$result = $this->authenticate($user, $password, substr($line,2)); $result = $this->authenticate($user, $password, substr($line,2));
// stop if server sent BYE response // stop if server sent BYE response
if ($result == -3) { if ($result == -3) {
return false; return false;
} }
} }
if (!is_resource($result) && $orig_method == 'CHECK') { if (!is_resource($result) && $orig_method == 'CHECK') {
$auth_method = 'PLAIN'; $auth_method = 'PLAIN';
} }
} }
if ($auth_method == 'PLAIN') { if ($auth_method == 'PLAIN') {
// do plain text auth // do plain text auth
$result = $this->login($user, $password); $result = $this->login($user, $password);
@ -727,7 +738,7 @@ class rcube_imap_generic
if ($this->selected == $mailbox) { if ($this->selected == $mailbox) {
return true; return true;
} }
if ($this->putLine("sel1 SELECT \"".$this->escape($mailbox).'"')) { if ($this->putLine("sel1 SELECT \"".$this->escape($mailbox).'"')) {
do { do {
$line = chop($this->readLine(300)); $line = chop($this->readLine(300));
@ -763,7 +774,7 @@ class rcube_imap_generic
if (empty($mailbox)) { if (empty($mailbox)) {
$mailbox = 'INBOX'; $mailbox = 'INBOX';
} }
$this->select($mailbox); $this->select($mailbox);
if ($this->selected == $mailbox) { if ($this->selected == $mailbox) {
return $this->recent; return $this->recent;
@ -777,7 +788,7 @@ class rcube_imap_generic
if ($refresh) { if ($refresh) {
$this->selected = ''; $this->selected = '';
} }
$this->select($mailbox); $this->select($mailbox);
if ($this->selected == $mailbox) { if ($this->selected == $mailbox) {
return $this->exists; return $this->exists;
@ -792,7 +803,7 @@ class rcube_imap_generic
if ($field == 'INTERNALDATE') { if ($field == 'INTERNALDATE') {
$field = 'ARRIVAL'; $field = 'ARRIVAL';
} }
$fields = array('ARRIVAL' => 1,'CC' => 1,'DATE' => 1, $fields = array('ARRIVAL' => 1,'CC' => 1,'DATE' => 1,
'FROM' => 1, 'SIZE' => 1, 'SUBJECT' => 1, 'TO' => 1); 'FROM' => 1, 'SIZE' => 1, 'SUBJECT' => 1, 'TO' => 1);
@ -804,9 +815,9 @@ class rcube_imap_generic
if (!$this->select($mailbox)) { if (!$this->select($mailbox)) {
return false; return false;
} }
$is_uid = $is_uid ? 'UID ' : ''; $is_uid = $is_uid ? 'UID ' : '';
// message IDs // message IDs
if (is_array($add)) if (is_array($add))
$add = $this->compressMessageSet(join(',', $add)); $add = $this->compressMessageSet(join(',', $add));
@ -828,14 +839,14 @@ class rcube_imap_generic
$data .= $line; $data .= $line;
} }
} while (!$this->startsWith($line, 's ', true, true)); } while (!$this->startsWith($line, 's ', true, true));
$result_code = $this->parseResult($line); $result_code = $this->parseResult($line);
if ($result_code != 0) { if ($result_code != 0) {
$this->error = "Sort: $line"; $this->error = "Sort: $line";
return false; return false;
} }
return preg_split('/\s+/', $data, -1, PREG_SPLIT_NO_EMPTY); return preg_split('/\s+/', $data, -1, PREG_SPLIT_NO_EMPTY);
} }
@ -851,9 +862,9 @@ class rcube_imap_generic
return false; return false;
} }
} }
$index_field = empty($index_field) ? 'DATE' : strtoupper($index_field); $index_field = empty($index_field) ? 'DATE' : strtoupper($index_field);
$fields_a['DATE'] = 1; $fields_a['DATE'] = 1;
$fields_a['INTERNALDATE'] = 4; $fields_a['INTERNALDATE'] = 4;
$fields_a['ARRIVAL'] = 4; $fields_a['ARRIVAL'] = 4;
@ -877,7 +888,7 @@ class rcube_imap_generic
if (!$this->select($mailbox)) { if (!$this->select($mailbox)) {
return false; return false;
} }
// build FETCH command string // build FETCH command string
$key = 'fhi0'; $key = 'fhi0';
$cmd = $uidfetch ? 'UID FETCH' : 'FETCH'; $cmd = $uidfetch ? 'UID FETCH' : 'FETCH';
@ -912,7 +923,7 @@ class rcube_imap_generic
if (preg_match('/^\* ([0-9]+) FETCH/', $line, $m)) { if (preg_match('/^\* ([0-9]+) FETCH/', $line, $m)) {
$id = $m[1]; $id = $m[1];
$flags = NULL; $flags = NULL;
if ($skip_deleted && preg_match('/FLAGS \(([^)]+)\)/', $line, $matches)) { if ($skip_deleted && preg_match('/FLAGS \(([^)]+)\)/', $line, $matches)) {
$flags = explode(' ', strtoupper($matches[1])); $flags = explode(' ', strtoupper($matches[1]));
if (in_array('\\DELETED', $flags)) { if (in_array('\\DELETED', $flags)) {
@ -962,28 +973,28 @@ class rcube_imap_generic
} }
} while (!$this->startsWith($line, $key, true, true)); } while (!$this->startsWith($line, $key, true, true));
return $result; return $result;
} }
private function compressMessageSet($message_set) private function compressMessageSet($message_set)
{ {
// given a comma delimited list of independent mid's, // given a comma delimited list of independent mid's,
// compresses by grouping sequences together // compresses by grouping sequences together
// if less than 255 bytes long, let's not bother // if less than 255 bytes long, let's not bother
if (strlen($message_set)<255) { if (strlen($message_set)<255) {
return $message_set; return $message_set;
} }
// see if it's already been compress // see if it's already been compress
if (strpos($message_set, ':') !== false) { if (strpos($message_set, ':') !== false) {
return $message_set; return $message_set;
} }
// separate, then sort // separate, then sort
$ids = explode(',', $message_set); $ids = explode(',', $message_set);
sort($ids); sort($ids);
$result = array(); $result = array();
$start = $prev = $ids[0]; $start = $prev = $ids[0];
@ -1006,7 +1017,7 @@ class rcube_imap_generic
} else { } else {
$result[] = $start.':'.$prev; $result[] = $start.':'.$prev;
} }
// return as comma separated string // return as comma separated string
return implode(',', $result); return implode(',', $result);
} }
@ -1051,14 +1062,14 @@ class rcube_imap_generic
$message_set = join(',', $message_set); $message_set = join(',', $message_set);
else if (empty($message_set)) else if (empty($message_set))
$message_set = '1:*'; $message_set = '1:*';
return $this->fetchHeaderIndex($mailbox, $message_set, 'UID', false); return $this->fetchHeaderIndex($mailbox, $message_set, 'UID', false);
} }
function fetchHeaders($mailbox, $message_set, $uidfetch=false, $bodystr=false, $add='') function fetchHeaders($mailbox, $message_set, $uidfetch=false, $bodystr=false, $add='')
{ {
$result = array(); $result = array();
if (!$this->select($mailbox)) { if (!$this->select($mailbox)) {
return false; return false;
} }
@ -1089,15 +1100,15 @@ class rcube_imap_generic
do { do {
$line = $this->readLine(1024); $line = $this->readLine(1024);
$line = $this->multLine($line); $line = $this->multLine($line);
if (!$line) if (!$line)
break; break;
$a = explode(' ', $line); $a = explode(' ', $line);
if (($line[0] == '*') && ($a[2] == 'FETCH')) { if (($line[0] == '*') && ($a[2] == 'FETCH')) {
$id = $a[1]; $id = $a[1];
$result[$id] = new rcube_mail_header; $result[$id] = new rcube_mail_header;
$result[$id]->id = $id; $result[$id]->id = $id;
$result[$id]->subject = ''; $result[$id]->subject = '';
@ -1133,16 +1144,16 @@ class rcube_imap_generic
} }
$time_str = str_replace('"', '', $time_str); $time_str = str_replace('"', '', $time_str);
// if time is gmt... // if time is gmt...
$time_str = str_replace('GMT','+0000',$time_str); $time_str = str_replace('GMT','+0000',$time_str);
$result[$id]->internaldate = $time_str; $result[$id]->internaldate = $time_str;
$result[$id]->timestamp = $this->StrToTime($time_str); $result[$id]->timestamp = $this->StrToTime($time_str);
$result[$id]->date = $time_str; $result[$id]->date = $time_str;
} }
// BODYSTRUCTURE // BODYSTRUCTURE
if($bodystr) { if($bodystr) {
while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/s', $line, $m)) { while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/s', $line, $m)) {
$line2 = $this->readLine(1024); $line2 = $this->readLine(1024);
@ -1168,13 +1179,13 @@ class rcube_imap_generic
// So, we'll read ahead, and if the one we're reading now is a valid header, we'll // So, we'll read ahead, and if the one we're reading now is a valid header, we'll
// process the previous line. Otherwise, we'll keep adding the strings until we come // process the previous line. Otherwise, we'll keep adding the strings until we come
// to the next valid header line. // to the next valid header line.
do { do {
$line = chop($this->readLine(300), "\r\n"); $line = chop($this->readLine(300), "\r\n");
// The preg_match below works around communigate imap, which outputs " UID <number>)". // 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. // Without this, the while statement continues on and gets the "FH0 OK completed" message.
// If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249. // If this loop gets the ending message, then the outer loop does not receive it from radline on line 1249.
// This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing // This in causes the if statement on line 1278 to never be true, which causes the headers to end up missing
// If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin // If the if statement was changed to pick up the fh0 from this loop, then it causes the outer loop to spin
// An alternative might be: // An alternative might be:
@ -1198,7 +1209,7 @@ class rcube_imap_generic
// patch from "Maksim Rubis" <siburny@hotmail.com> // patch from "Maksim Rubis" <siburny@hotmail.com>
} while ($line[0] != ')' && !$this->startsWith($line, $key, true)); } while ($line[0] != ')' && !$this->startsWith($line, $key, true));
if (strncmp($line, $key, strlen($key))) { if (strncmp($line, $key, strlen($key))) {
// process header, fill rcube_mail_header obj. // process header, fill rcube_mail_header obj.
// initialize // initialize
if (is_array($headers)) { if (is_array($headers)) {
@ -1211,10 +1222,10 @@ class rcube_imap_generic
// create array with header field:data // create array with header field:data
while ( list($lines_key, $str) = each($lines) ) { while ( list($lines_key, $str) = each($lines) ) {
list($field, $string) = $this->splitHeaderLine($str); list($field, $string) = $this->splitHeaderLine($str);
$field = strtolower($field); $field = strtolower($field);
$string = preg_replace('/\n\s*/', ' ', $string); $string = preg_replace('/\n\s*/', ' ', $string);
switch ($field) { switch ($field) {
case 'date'; case 'date';
$result[$id]->date = $string; $result[$id]->date = $string;
@ -1280,7 +1291,7 @@ class rcube_imap_generic
if (!empty($flags_str)) { if (!empty($flags_str)) {
$flags_str = preg_replace('/[\\\"]/', '', $flags_str); $flags_str = preg_replace('/[\\\"]/', '', $flags_str);
$flags_a = explode(' ', $flags_str); $flags_a = explode(' ', $flags_str);
if (is_array($flags_a)) { if (is_array($flags_a)) {
// reset($flags_a); // reset($flags_a);
foreach($flags_a as $flag) { foreach($flags_a as $flag) {
@ -1343,12 +1354,12 @@ class rcube_imap_generic
$c = count($a); $c = count($a);
if ($c > 0) { if ($c > 0) {
// Strategy: // Strategy:
// First, we'll create an "index" array. // First, we'll create an "index" array.
// Then, we'll use sort() on that array, // Then, we'll use sort() on that array,
// and use that to sort the main array. // and use that to sort the main array.
// create "index" array // create "index" array
$index = array(); $index = array();
reset($a); reset($a);
@ -1366,7 +1377,7 @@ class rcube_imap_generic
} }
$index[$key]=$data; $index[$key]=$data;
} }
// sort index // sort index
$i = 0; $i = 0;
if ($flag == 'ASC') { if ($flag == 'ASC') {
@ -1375,7 +1386,7 @@ class rcube_imap_generic
arsort($index); arsort($index);
} }
// form new array based on index // form new array based on index
$result = array(); $result = array();
reset($index); reset($index);
while (list($key, $val) = each($index)) { while (list($key, $val) = each($index)) {
@ -1383,7 +1394,7 @@ class rcube_imap_generic
$i++; $i++;
} }
} }
return $result; return $result;
} }
@ -1392,7 +1403,7 @@ class rcube_imap_generic
if (!$this->select($mailbox)) { if (!$this->select($mailbox)) {
return -1; return -1;
} }
$c = 0; $c = 0;
$command = $messages ? "UID EXPUNGE $messages" : "EXPUNGE"; $command = $messages ? "UID EXPUNGE $messages" : "EXPUNGE";
@ -1406,7 +1417,7 @@ class rcube_imap_generic
$c++; $c++;
} }
} while (!$this->startsWith($line, 'exp1', true, true)); } while (!$this->startsWith($line, 'exp1', true, true));
if ($this->parseResult($line) == 0) { if ($this->parseResult($line) == 0) {
$this->selected = ''; // state has changed, need to reselect $this->selected = ''; // state has changed, need to reselect
return $c; return $c;
@ -1420,13 +1431,13 @@ class rcube_imap_generic
if ($mod != '+' && $mod != '-') { if ($mod != '+' && $mod != '-') {
return -1; return -1;
} }
$flag = $this->flags[strtoupper($flag)]; $flag = $this->flags[strtoupper($flag)];
if (!$this->select($mailbox)) { if (!$this->select($mailbox)) {
return -1; return -1;
} }
$c = 0; $c = 0;
if (!$this->putLine("flg UID STORE $messages {$mod}FLAGS ($flag)")) { if (!$this->putLine("flg UID STORE $messages {$mod}FLAGS ($flag)")) {
return false; return false;
@ -1464,11 +1475,11 @@ class rcube_imap_generic
if (empty($from) || empty($to)) { if (empty($from) || empty($to)) {
return -1; return -1;
} }
if (!$this->select($from)) { if (!$this->select($from)) {
return -1; return -1;
} }
$this->putLine("cpy1 UID COPY $messages \"".$this->escape($to)."\""); $this->putLine("cpy1 UID COPY $messages \"".$this->escape($to)."\"");
$line = $this->readReply(); $line = $this->readReply();
return $this->parseResult($line); return $this->parseResult($line);
@ -1529,7 +1540,7 @@ class rcube_imap_generic
$node += $this->parseThread($str, $start + 1, $off - 1, $root, $parent, $depth, $depthmap, $haschildren); $node += $this->parseThread($str, $start + 1, $off - 1, $root, $parent, $depth, $depthmap, $haschildren);
} }
} }
return $node; return $node;
} }
@ -1542,7 +1553,7 @@ class rcube_imap_generic
$encoding = $encoding ? trim($encoding) : 'US-ASCII'; $encoding = $encoding ? trim($encoding) : 'US-ASCII';
$algorithm = $algorithm ? trim($algorithm) : 'REFERENCES'; $algorithm = $algorithm ? trim($algorithm) : 'REFERENCES';
$criteria = $criteria ? 'ALL '.trim($criteria) : 'ALL'; $criteria = $criteria ? 'ALL '.trim($criteria) : 'ALL';
if (!$this->putLineC("thrd1 THREAD $algorithm $encoding $criteria")) { if (!$this->putLineC("thrd1 THREAD $algorithm $encoding $criteria")) {
return false; return false;
} }
@ -1562,7 +1573,7 @@ class rcube_imap_generic
} }
$this->error = "Thread: $line"; $this->error = "Thread: $line";
return false; return false;
} }
function search($folder, $criteria, $return_uid=false) function search($folder, $criteria, $return_uid=false)
@ -1593,7 +1604,7 @@ class rcube_imap_generic
} }
$this->error = "Search: $line"; $this->error = "Search: $line";
return false; return false;
} }
function move($messages, $from, $to) function move($messages, $from, $to)
@ -1601,7 +1612,7 @@ class rcube_imap_generic
if (!$from || !$to) { if (!$from || !$to) {
return -1; return -1;
} }
$r = $this->copy($messages, $from, $to); $r = $this->copy($messages, $from, $to);
if ($r==0) { if ($r==0) {
@ -1625,11 +1636,11 @@ class rcube_imap_generic
if (empty($mailbox)) { if (empty($mailbox)) {
$mailbox = '*'; $mailbox = '*';
} }
if (empty($ref) && $this->rootdir) { if (empty($ref) && $this->rootdir) {
$ref = $this->rootdir; $ref = $this->rootdir;
} }
if ($subscribed) { if ($subscribed) {
$key = 'lsb'; $key = 'lsb';
$command = 'LSUB'; $command = 'LSUB';
@ -1644,7 +1655,7 @@ class rcube_imap_generic
$this->error = "Couldn't send $command command"; $this->error = "Couldn't send $command command";
return false; return false;
} }
// get folder list // get folder list
do { do {
$line = $this->readLine(500); $line = $this->readLine(500);
@ -1677,7 +1688,7 @@ class rcube_imap_generic
if (!$this->select($mailbox)) { if (!$this->select($mailbox)) {
return false; return false;
} }
$result = false; $result = false;
$parts = (array) $parts; $parts = (array) $parts;
$key = 'fmh0'; $key = 'fmh0';
@ -1688,14 +1699,14 @@ class rcube_imap_generic
// format request // format request
foreach($parts as $part) foreach($parts as $part)
$peeks[] = "BODY.PEEK[$part.$type]"; $peeks[] = "BODY.PEEK[$part.$type]";
$request = "$key FETCH $id (" . implode(' ', $peeks) . ')'; $request = "$key FETCH $id (" . implode(' ', $peeks) . ')';
// send request // send request
if (!$this->putLine($request)) { if (!$this->putLine($request)) {
return false; return false;
} }
do { do {
$line = $this->readLine(1000); $line = $this->readLine(1000);
$line = $this->multLine($line); $line = $this->multLine($line);
@ -1740,7 +1751,7 @@ class rcube_imap_generic
default: default:
$mode = 0; $mode = 0;
} }
$reply_key = '* ' . $id; $reply_key = '* ' . $id;
$result = false; $result = false;
@ -1788,11 +1799,11 @@ class rcube_imap_generic
$sizeStr = substr($line, $from, $len); $sizeStr = substr($line, $from, $len);
$bytes = (int)$sizeStr; $bytes = (int)$sizeStr;
$prev = ''; $prev = '';
while ($bytes > 0) { while ($bytes > 0) {
$line = $this->readLine(1024); $line = $this->readLine(1024);
$len = strlen($line); $len = strlen($line);
if ($len > $bytes) { if ($len > $bytes) {
$line = substr($line, 0, $bytes); $line = substr($line, 0, $bytes);
$len = strlen($line); $len = strlen($line);
@ -1811,7 +1822,7 @@ class rcube_imap_generic
} }
else else
$prev = ''; $prev = '';
if ($file) if ($file)
fwrite($file, base64_decode($line)); fwrite($file, base64_decode($line));
else if ($print) else if ($print)
@ -1847,7 +1858,7 @@ class rcube_imap_generic
} }
} }
} }
// read in anything up until last line // read in anything up until last line
if (!$end) if (!$end)
do { do {
@ -1922,7 +1933,7 @@ class rcube_imap_generic
{ {
$query = 'usub1 UNSUBSCRIBE "' . $this->escape($folder) . '"'; $query = 'usub1 UNSUBSCRIBE "' . $this->escape($folder) . '"';
$this->putLine($query); $this->putLine($query);
$line = trim($this->readLine(512)); $line = trim($this->readLine(512));
return ($this->parseResult($line) == 0); return ($this->parseResult($line) == 0);
} }
@ -1959,7 +1970,7 @@ class rcube_imap_generic
do { do {
$line = $this->readLine(); $line = $this->readLine();
} while (!$this->startsWith($line, 'a ', true, true)); } while (!$this->startsWith($line, 'a ', true, true));
$result = ($this->parseResult($line) == 0); $result = ($this->parseResult($line) == 0);
if (!$result) { if (!$result) {
$this->error = $line; $this->error = $line;
@ -1976,17 +1987,17 @@ class rcube_imap_generic
if (!$folder) { if (!$folder) {
return false; return false;
} }
// open message file // open message file
$in_fp = false; $in_fp = false;
if (file_exists(realpath($path))) { if (file_exists(realpath($path))) {
$in_fp = fopen($path, 'r'); $in_fp = fopen($path, 'r');
} }
if (!$in_fp) { if (!$in_fp) {
$this->error = "Couldn't open $path for reading"; $this->error = "Couldn't open $path for reading";
return false; return false;
} }
$len = filesize($path); $len = filesize($path);
if (!$len) { if (!$len) {
return false; return false;
@ -2036,7 +2047,7 @@ class rcube_imap_generic
return $result; return $result;
} }
$this->error = "Couldn't send command \"$request\""; $this->error = "Couldn't send command \"$request\"";
return false; return false;
} }
@ -2074,7 +2085,7 @@ class rcube_imap_generic
*/ */
$result = false; $result = false;
$quota_lines = array(); $quota_lines = array();
// get line(s) containing quota info // get line(s) containing quota info
if ($this->putLine('QUOT1 GETQUOTAROOT "INBOX"')) { if ($this->putLine('QUOT1 GETQUOTAROOT "INBOX"')) {
do { do {
@ -2084,24 +2095,24 @@ class rcube_imap_generic
} }
} while (!$this->startsWith($line, 'QUOT1', true, true)); } while (!$this->startsWith($line, 'QUOT1', true, true));
} }
// return false if not found, parse if found // return false if not found, parse if found
$min_free = PHP_INT_MAX; $min_free = PHP_INT_MAX;
foreach ($quota_lines as $key => $quota_line) { foreach ($quota_lines as $key => $quota_line) {
$quota_line = preg_replace('/[()]/', '', $quota_line); $quota_line = preg_replace('/[()]/', '', $quota_line);
$parts = explode(' ', $quota_line); $parts = explode(' ', $quota_line);
$storage_part = array_search('STORAGE', $parts); $storage_part = array_search('STORAGE', $parts);
if (!$storage_part) if (!$storage_part)
continue; continue;
$used = intval($parts[$storage_part+1]); $used = intval($parts[$storage_part+1]);
$total = intval($parts[$storage_part+2]); $total = intval($parts[$storage_part+2]);
$free = $total - $used; $free = $total - $used;
// return lowest available space from all quotas // return lowest available space from all quotas
if ($free < $min_free) { if ($free < $min_free) {
$min_free = $free; $min_free = $free;
$result['used'] = $used; $result['used'] = $used;
$result['total'] = $total; $result['total'] = $total;
$result['percent'] = min(100, round(($used/max(1,$total))*100)); $result['percent'] = min(100, round(($used/max(1,$total))*100));
@ -2137,7 +2148,7 @@ class rcube_imap_generic
$ts = (int) $ts; $ts = (int) $ts;
return $ts < 0 ? 0 : $ts; return $ts < 0 ? 0 : $ts;
} }
private function SplitHeaderLine($string) private function SplitHeaderLine($string)
@ -2162,7 +2173,7 @@ class rcube_imap_generic
$data = array(); $data = array();
$in_quotes = false; $in_quotes = false;
$elem = 0; $elem = 0;
for ($i;$i<$len;$i++) { for ($i;$i<$len;$i++) {
$c = (string)$str[$i]; $c = (string)$str[$i];
if ($c == '(' && !$in_quotes) { if ($c == '(' && !$in_quotes) {
@ -2185,18 +2196,18 @@ class rcube_imap_generic
$data[$elem].=$c; $data[$elem].=$c;
} }
} }
return $data; return $data;
} }
private function escape($string) private function escape($string)
{ {
return strtr($string, array('"'=>'\\"', '\\' => '\\\\')); return strtr($string, array('"'=>'\\"', '\\' => '\\\\'));
} }
private function unEscape($string) private function unEscape($string)
{ {
return strtr($string, array('\\"'=>'"', '\\\\' => '\\')); return strtr($string, array('\\"'=>'"', '\\\\' => '\\'));
} }
} }

Loading…
Cancel
Save