From e4e38e02cfe626ffeda26b1d4a08df7a6cd3997d Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Wed, 02 Feb 2011 14:41:41 -0500
Subject: [PATCH] Fix inconsistency in de_DE localization (#1487749)
---
program/include/rcube_imap_generic.php | 239 +++++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 159 insertions(+), 80 deletions(-)
diff --git a/program/include/rcube_imap_generic.php b/program/include/rcube_imap_generic.php
index 512e7e4..e8b1fd4 100644
--- a/program/include/rcube_imap_generic.php
+++ b/program/include/rcube_imap_generic.php
@@ -5,7 +5,7 @@
| program/include/rcube_imap_generic.php |
| |
| This file is part of the Roundcube Webmail client |
- | Copyright (C) 2005-2010, Roundcube Dev. - Switzerland |
+ | Copyright (C) 2005-2010, The Roundcube Dev Team |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@@ -109,6 +109,8 @@
private $prefs;
private $cmd_tag;
private $cmd_num = 0;
+ private $_debug = false;
+ private $_debug_handler = false;
const ERROR_OK = 0;
const ERROR_NO = -1;
@@ -142,8 +144,8 @@
if (!$this->fp)
return false;
- if (!empty($this->prefs['debug_mode'])) {
- write_log('imap', 'C: '. rtrim($string));
+ if ($this->_debug) {
+ $this->debug('C: '. rtrim($string));
}
$res = fwrite($this->fp, $string . ($endln ? "\r\n" : ''));
@@ -231,8 +233,8 @@
$this->fp = null;
break;
}
- if (!empty($this->prefs['debug_mode'])) {
- write_log('imap', 'S: '. rtrim($buffer));
+ if ($this->_debug) {
+ $this->debug('S: '. rtrim($buffer));
}
$line .= $buffer;
} while ($buffer[strlen($buffer)-1] != "\n");
@@ -268,8 +270,8 @@
while ($len < $bytes && !feof($this->fp))
{
$d = fread($this->fp, $bytes-$len);
- if (!empty($this->prefs['debug_mode'])) {
- write_log('imap', 'S: '. $d);
+ if ($this->_debug) {
+ $this->debug('S: '. $d);
}
$data .= $d;
$data_len = strlen($data);
@@ -369,10 +371,43 @@
return false;
}
- function getCapability($name)
+ private function hasCapability($name)
{
+ if (empty($this->capability) || $name == '') {
+ return false;
+ }
+
if (in_array($name, $this->capability)) {
return true;
+ }
+ else if (strpos($name, '=')) {
+ return false;
+ }
+
+ $result = array();
+ foreach ($this->capability as $cap) {
+ $entry = explode('=', $cap);
+ if ($entry[0] == $name) {
+ $result[] = $entry[1];
+ }
+ }
+
+ return !empty($result) ? $result : false;
+ }
+
+ /**
+ * Capabilities checker
+ *
+ * @param string $name Capability name
+ *
+ * @return mixed Capability values array for key=value pairs, true/false for others
+ */
+ function getCapability($name)
+ {
+ $result = $this->hasCapability($name);
+
+ if (!empty($result)) {
+ return $result;
}
else if ($this->capability_readed) {
return false;
@@ -388,11 +423,7 @@
$this->capability_readed = true;
- if (in_array($name, $this->capability)) {
- return true;
- }
-
- return false;
+ return $this->hasCapability($name);
}
function clearCapability()
@@ -686,8 +717,8 @@
$line = trim(fgets($this->fp, 8192));
- if ($this->prefs['debug_mode'] && $line) {
- write_log('imap', 'S: '. $line);
+ if ($this->_debug && $line) {
+ $this->debug('S: '. $line);
}
// Connected to wrong port or connection error?
@@ -733,17 +764,17 @@
// check for supported auth methods
if ($auth_method == 'CHECK') {
- if ($this->getCapability('AUTH=DIGEST-MD5')) {
- $auth_methods[] = 'DIGEST-MD5';
- }
- if ($this->getCapability('AUTH=CRAM-MD5') || $this->getCapability('AUTH=CRAM_MD5')) {
- $auth_methods[] = 'CRAM-MD5';
- }
- if ($this->getCapability('AUTH=PLAIN')) {
- $auth_methods[] = 'PLAIN';
+ if ($auth_caps = $this->getCapability('AUTH')) {
+ $auth_methods = $auth_caps;
}
// RFC 2595 (LOGINDISABLED) LOGIN disabled when connection is not secure
- if (!$this->getCapability('LOGINDISABLED')) {
+ $login_disabled = $this->getCapability('LOGINDISABLED');
+ if (($key = array_search('LOGIN', $auth_methods)) !== false) {
+ if ($login_disabled) {
+ unset($auth_methods[$key]);
+ }
+ }
+ else if (!$login_disabled) {
$auth_methods[] = 'LOGIN';
}
}
@@ -764,8 +795,10 @@
// Authenticate
foreach ($auth_methods as $method) {
switch ($method) {
- case 'DIGEST-MD5':
+ case 'CRAM_MD5':
+ $method = 'CRAM-MD5';
case 'CRAM-MD5':
+ case 'DIGEST-MD5':
case 'PLAIN':
$result = $this->authenticate($user, $password, $method);
break;
@@ -1461,7 +1494,7 @@
// INTERNALDATE "16-Nov-2008 21:08:46 +0100" BODYSTRUCTURE (...)
// BODY[HEADER.FIELDS ...
- if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY/s', $line, $matches)) {
+ if (preg_match('/^\* [0-9]+ FETCH \((.*) BODY/sU', $line, $matches)) {
$str = $matches[1];
// swap parents with quotes, then explode
@@ -1498,7 +1531,7 @@
// BODYSTRUCTURE
if ($bodystr) {
- while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/s', $line, $m)) {
+ while (!preg_match('/ BODYSTRUCTURE (.*) BODY\[HEADER.FIELDS/sU', $line, $m)) {
$line2 = $this->readLine(1024);
$line .= $this->multLine($line2, true);
}
@@ -2604,13 +2637,13 @@
*/
function getACL($mailbox)
{
- list($code, $response) = $this->execute('GETACL', $this->escape($mailbox));
+ list($code, $response) = $this->execute('GETACL', array($this->escape($mailbox)));
if ($code == self::ERROR_OK && preg_match('/^\* ACL /i', $response)) {
// Parse server response (remove "* ACL ")
$response = substr($response, 6);
$ret = $this->tokenizeResponse($response);
- $mbox = array_unshift($ret);
+ $mbox = array_shift($ret);
$size = count($ret);
// Create user-rights hash array
@@ -2677,7 +2710,7 @@
*/
function myRights($mailbox)
{
- list($code, $response) = $this->execute('MYRIGHTS', array($this->escape(mailbox)));
+ list($code, $response) = $this->execute('MYRIGHTS', array($this->escape($mailbox)));
if ($code == self::ERROR_OK && preg_match('/^\* MYRIGHTS /i', $response)) {
// Parse server response (remove "* MYRIGHTS ")
@@ -2804,37 +2837,46 @@
list($code, $response) = $this->execute('GETMETADATA', array(
$this->escape($mailbox), $optlist));
- if ($code == self::ERROR_OK && preg_match('/^\* METADATA /i', $response)) {
- // Parse server response (remove "* METADATA ")
- $response = substr($response, 11);
- $ret_mbox = $this->tokenizeResponse($response, 1);
- $data = $this->tokenizeResponse($response);
+ if ($code == self::ERROR_OK) {
+ $result = array();
+ $data = $this->tokenizeResponse($response);
// The METADATA response can contain multiple entries in a single
// response or multiple responses for each entry or group of entries
if (!empty($data) && ($size = count($data))) {
for ($i=0; $i<$size; $i++) {
- if (is_array($data[$i])) {
+ if (isset($mbox) && is_array($data[$i])) {
$size_sub = count($data[$i]);
for ($x=0; $x<$size_sub; $x++) {
- $data[$data[$i][$x]] = $data[$i][++$x];
+ $result[$mbox][$data[$i][$x]] = $data[$i][++$x];
}
unset($data[$i]);
}
- else if ($data[$i] == '*' && $data[$i+1] == 'METADATA') {
- unset($data[$i]); // "*"
- unset($data[++$i]); // "METADATA"
- unset($data[++$i]); // Mailbox
+ else if ($data[$i] == '*') {
+ if ($data[$i+1] == 'METADATA') {
+ $mbox = $data[$i+2];
+ unset($data[$i]); // "*"
+ unset($data[++$i]); // "METADATA"
+ unset($data[++$i]); // Mailbox
+ }
+ // get rid of other untagged responses
+ else {
+ unset($mbox);
+ unset($data[$i]);
+ }
}
- else {
- $data[$data[$i]] = $data[++$i];
+ else if (isset($mbox)) {
+ $result[$mbox][$data[$i]] = $data[++$i];
unset($data[$i]);
unset($data[$i-1]);
+ }
+ else {
+ unset($data[$i]);
}
}
}
- return $data;
+ return $result;
}
return NULL;
@@ -2870,8 +2912,9 @@
$value = sprintf("{%d}\r\n%s", strlen($value), $value);
}
+ // ANNOTATEMORE drafts before version 08 require quoted parameters
$entries[] = sprintf('%s (%s %s)',
- $this->escape($name), $this->escape($attr), $value);
+ $this->escape($name, true), $this->escape($attr, true), $value);
}
$entries = implode(' ', $entries);
@@ -2921,8 +2964,9 @@
$entries = array($entries);
}
// create entries string
+ // ANNOTATEMORE drafts before version 08 require quoted parameters
foreach ($entries as $idx => $name) {
- $entries[$idx] = $this->escape($name);
+ $entries[$idx] = $this->escape($name, true);
}
$entries = '(' . implode(' ', $entries) . ')';
@@ -2931,50 +2975,65 @@
}
// create entries string
foreach ($attribs as $idx => $name) {
- $attribs[$idx] = $this->escape($name);
+ $attribs[$idx] = $this->escape($name, true);
}
$attribs = '(' . implode(' ', $attribs) . ')';
list($code, $response) = $this->execute('GETANNOTATION', array(
$this->escape($mailbox), $entries, $attribs));
- if ($code == self::ERROR_OK && preg_match('/^\* ANNOTATION /i', $response)) {
- // Parse server response (remove "* ANNOTATION ")
- $response = substr($response, 13);
- $ret_mbox = $this->tokenizeResponse($response, 1);
- $data = $this->tokenizeResponse($response);
- $res = array();
+ if ($code == self::ERROR_OK) {
+ $result = array();
+ $data = $this->tokenizeResponse($response);
// Here we returns only data compatible with METADATA result format
if (!empty($data) && ($size = count($data))) {
for ($i=0; $i<$size; $i++) {
- $entry = $data[$i++];
- if (is_array($entry)) {
+ $entry = $data[$i];
+ if (isset($mbox) && is_array($entry)) {
$attribs = $entry;
$entry = $last_entry;
}
- else
- $attribs = $data[$i++];
+ else if ($entry == '*') {
+ if ($data[$i+1] == 'ANNOTATION') {
+ $mbox = $data[$i+2];
+ unset($data[$i]); // "*"
+ unset($data[++$i]); // "ANNOTATION"
+ unset($data[++$i]); // Mailbox
+ }
+ // get rid of other untagged responses
+ else {
+ unset($mbox);
+ unset($data[$i]);
+ }
+ continue;
+ }
+ else if (isset($mbox)) {
+ $attribs = $data[++$i];
+ }
+ else {
+ unset($data[$i]);
+ continue;
+ }
if (!empty($attribs)) {
for ($x=0, $len=count($attribs); $x<$len;) {
$attr = $attribs[$x++];
$value = $attribs[$x++];
if ($attr == 'value.priv') {
- $res['/private' . $entry] = $value;
+ $result[$mbox]['/private' . $entry] = $value;
}
else if ($attr == 'value.shared') {
- $res['/shared' . $entry] = $value;
+ $result[$mbox]['/shared' . $entry] = $value;
}
}
}
$last_entry = $entry;
- unset($data[$i-1]);
- unset($data[$i-2]);
+ unset($data[$i]);
}
}
- return $res;
+ return $result;
}
return NULL;
@@ -3164,21 +3223,7 @@
*/
private function strToTime($date)
{
- // support non-standard "GMTXXXX" literal
- $date = preg_replace('/GMT\s*([+-][0-9]+)/', '\\1', $date);
- // if date parsing fails, we have a date in non-rfc format.
- // remove token from the end and try again
- while ((($ts = @strtotime($date))===false) || ($ts < 0)) {
- $d = explode(' ', $date);
- array_pop($d);
- if (!$d) {
- break;
- }
- $date = implode(' ', $d);
- }
-
- $ts = (int) $ts;
-
+ $ts = (int) rcube_strtotime($date);
return $ts < 0 ? 0 : $ts;
}
@@ -3211,12 +3256,13 @@
/**
* Escapes a string when it contains special characters (RFC3501)
*
- * @param string $string IMAP string
+ * @param string $string IMAP string
+ * @param boolean $force_quotes Forces string quoting
*
* @return string Escaped string
* @todo String literals, lists
*/
- static function escape($string)
+ static function escape($string, $force_quotes=false)
{
if ($string === null) {
return 'NIL';
@@ -3224,7 +3270,9 @@
else if ($string === '') {
return '""';
}
- else if (preg_match('/([\x00-\x20\x28-\x29\x7B\x25\x2A\x22\x5C\x5D\x7F]+)/', $string)) {
+ else if ($force_quotes ||
+ preg_match('/([\x00-\x20\x28-\x29\x7B\x25\x2A\x22\x5C\x5D\x7F]+)/', $string)
+ ) {
// string: special chars: SP, CTL, (, ), {, %, *, ", \, ]
return '"' . strtr($string, array('"'=>'\\"', '\\' => '\\\\')) . '"';
}
@@ -3238,4 +3286,35 @@
return strtr($string, array('\\"'=>'"', '\\\\' => '\\'));
}
+ /**
+ * Set the value of the debugging flag.
+ *
+ * @param boolean $debug New value for the debugging flag.
+ *
+ * @access public
+ * @since 0.5-stable
+ */
+ function setDebug($debug, $handler = null)
+ {
+ $this->_debug = $debug;
+ $this->_debug_handler = $handler;
+ }
+
+ /**
+ * Write the given debug text to the current debug output handler.
+ *
+ * @param string $message Debug mesage text.
+ *
+ * @access private
+ * @since 0.5-stable
+ */
+ private function debug($message)
+ {
+ if ($this->_debug_handler) {
+ call_user_func_array($this->_debug_handler, array(&$this, $message));
+ } else {
+ echo "DEBUG: $message\n";
+ }
+ }
+
}
--
Gitblit v1.9.1