alecpl
2011-04-17 8ffd08a7398d044dc7e9f5deecc76a29c6aa270e
- Aplied fixes from trunk


9 files modified
195 ■■■■■ changed files
CHANGELOG 5 ●●●●● patch | view | raw | blame | history
program/include/rcube_smtp.php 9 ●●●● patch | view | raw | blame | history
program/include/rcube_template.php 26 ●●●●● patch | view | raw | blame | history
program/js/app.js 20 ●●●●● patch | view | raw | blame | history
program/js/list.js 102 ●●●●● patch | view | raw | blame | history
program/lib/Net/SMTP.php 21 ●●●● patch | view | raw | blame | history
program/localization/de_CH/messages.inc 4 ●●●● patch | view | raw | blame | history
program/localization/de_DE/messages.inc 6 ●●●● patch | view | raw | blame | history
program/localization/index.inc 2 ●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,8 @@
CHANGELOG Roundcube Webmail
===========================
- PEAR::Net_SMTP 1.5.2, fixed timeout issue (#1487843)
- Fix bug where template name without plugin prefix was used in render_page hook
- Support 'abort' and 'result' response in 'preferences_save' hook, add error handling
- Fix bug where some content would cause hang on html2text conversion (#1487863)
- Improve space-stuffing handling in format=flowed messages (#1487861)
@@ -8,7 +10,6 @@
- Added workaround for some IMAP server with broken STATUS response (#1487859)
- Fix bug where default_charset was not used for text messages (#1487836)
- Stateless request tokens. No keep-alive necessary on login page (#1487829)
- PEAR::Net_SMTP 1.5.1
- Force names of unique constraints in PostgreSQL DDL
- Add code for prevention from IMAP connection hangs when server closes socket unexpectedly
- Remove redundant DELETE query (for old session deletion) on login
@@ -16,7 +17,7 @@
- Fix some emails are not shown using Cyrus IMAP (#1487820)
- Fix handling of mime-encoded words with non-integral number of octets in a word (#1487801)
- Fix parsing links with non-printable characters inside (#1487805)
- Fixed de_CH Localization bugs (#1487773)
- Fixed de_CH/de_DE localization bugs (#1487773)
- Add variable for 'Today' label in date_today option (#1486120)
- Applied plugin changes since 0.5-stable release
- Fix SQL query in rcube_user::query() so it uses index on MySQL again
program/include/rcube_smtp.php
@@ -105,7 +105,7 @@
    $this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host);
    if($RCMAIL->config->get('smtp_debug'))
    if ($RCMAIL->config->get('smtp_debug'))
      $this->conn->setDebug(true, array($this, 'debug_handler'));
    // try to connect to server and exit on failure
@@ -118,6 +118,13 @@
      return false;
    }
    // workaround for timeout bug in Net_SMTP 1.5.[0-1] (#1487843)
    if (method_exists($this->conn, 'setTimeout')
      && ($timeout = ini_get('default_socket_timeout'))
    ) {
      $this->conn->setTimeout($timeout);
    }
    $smtp_user = str_replace('%u', $_SESSION['username'], $CONFIG['smtp_user']);
    $smtp_pass = str_replace('%p', $RCMAIL->decrypt($_SESSION['password']), $CONFIG['smtp_pass']);
    $smtp_auth_type = empty($CONFIG['smtp_auth_type']) ? NULL : $CONFIG['smtp_auth_type'];
program/include/rcube_template.php
@@ -373,16 +373,19 @@
    private function parse($name = 'main', $exit = true)
    {
        $skin_path = $this->config['skin_path'];
        $plugin = false;
        $plugin    = false;
        $realname  = $name;
        $temp      = explode('.', $name, 2);
        $this->plugin_skin_path = null;
        $temp = explode(".", $name, 2);
        if (count($temp) > 1) {
            $plugin = $temp[0];
            $name = $temp[1];
            $skin_dir = $plugin . '/skins/' . $this->config['skin'];
            $plugin    = $temp[0];
            $name      = $temp[1];
            $skin_dir  = $plugin . '/skins/' . $this->config['skin'];
            $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir;
            if (!is_dir($skin_path)) {  // fallback to default skin
            // fallback to default skin
            if (!is_dir($skin_path)) {
                $skin_dir = $plugin . '/skins/default';
                $skin_path = $this->plugin_skin_path = $this->app->plugins->dir . $skin_dir;
            }
@@ -390,12 +393,13 @@
        $path = "$skin_path/templates/$name.html";
        if (!is_readable($path) && $this->deprecated_templates[$name]) {
            $path = "$skin_path/templates/".$this->deprecated_templates[$name].".html";
        if (!is_readable($path) && $this->deprecated_templates[$realname]) {
            $path = "$skin_path/templates/".$this->deprecated_templates[$realname].".html";
            if (is_readable($path))
                raise_error(array('code' => 502, 'type' => 'php',
                    'file' => __FILE__, 'line' => __LINE__,
                    'message' => "Using deprecated template '".$this->deprecated_templates[$name]."' in ".$this->config['skin_path']."/templates. Please rename to '".$name."'"),
                    'message' => "Using deprecated template '".$this->deprecated_templates[$realname]
                        ."' in ".$this->config['skin_path']."/templates. Please rename to '".$realname."'"),
                true, false);
        }
@@ -406,7 +410,7 @@
                'type' => 'php',
                'line' => __LINE__,
                'file' => __FILE__,
                'message' => 'Error loading template for '.$name
                'message' => 'Error loading template for '.$realname
                ), true, true);
            return false;
        }
@@ -422,7 +426,7 @@
        $output = $this->parse_xml($output);
        // trigger generic hook where plugins can put additional content to the page
        $hook = $this->app->plugins->exec_hook("render_page", array('template' => $name, 'content' => $output));
        $hook = $this->app->plugins->exec_hook("render_page", array('template' => $realname, 'content' => $output));
        // add debug console
        if ($this->config['debug_level'] & 8) {
program/js/app.js
@@ -4650,17 +4650,18 @@
  // and for setting some message list global variables
  this.set_message_coltypes = function(coltypes, repl)
  {
    this.env.coltypes = coltypes;
    var list = this.message_list,
      thead = list ? list.list.tHead : null,
      cell, col, n, len, th, tr;
    // set correct list titles
    var thead = this.gui_objects.messagelist ? this.gui_objects.messagelist.tHead : null,
      cell, col, n, len;
    this.env.coltypes = coltypes;
    // replace old column headers
    if (thead) {
      if (repl) {
        var th = document.createElement('thead'),
          tr = document.createElement('tr');
        th = document.createElement('thead');
        tr = document.createElement('tr');
        for (c=0, len=repl.length; c < len; c++) {
          cell = document.createElement('td');
          cell.innerHTML = repl[c].html;
@@ -4694,15 +4695,16 @@
    if ((n = $.inArray('subject', this.env.coltypes)) >= 0) {
      this.set_env('subject_col', n);
      if (this.message_list)
        this.message_list.subject_col = n;
      if (list)
        list.subject_col = n;
    }
    if ((n = $.inArray('flag', this.env.coltypes)) >= 0)
      this.set_env('flagged_col', n);
    if ((n = $.inArray('status', this.env.coltypes)) >= 0)
      this.set_env('status_col', n);
    this.message_list.init_header();
    if (list)
      list.init_header();
  };
  // replace content of row count display
program/js/list.js
@@ -102,8 +102,8 @@
{
  // make references in internal array and set event handlers
  if (row && String(row.id).match(/rcmrow([a-z0-9\-_=\+\/]+)/i)) {
    var self = this;
    var uid = RegExp.$1;
    var self = this,
      uid = RegExp.$1;
    row.uid = uid;
    this.rows[uid] = {uid:uid, id:row.id, obj:row};
@@ -170,6 +170,10 @@
  if (sel)
    this.clear_selection();
  // reset scroll position (in Opera)
  if (this.frame)
    this.frame.scrollTop = 0;
},
@@ -212,10 +216,10 @@
 */
focus: function(e)
{
  var id;
  var n, id;
  this.focused = true;
  for (var n in this.selection) {
  for (n in this.selection) {
    id = this.selection[n];
    if (this.rows[id] && this.rows[id].obj) {
      $(this.rows[id].obj).addClass('selected').removeClass('unfocused');
@@ -236,9 +240,9 @@
 */
blur: function()
{
  var id;
  var n, id;
  this.focused = false;
  for (var n in this.selection) {
  for (n in this.selection) {
    id = this.selection[n];
    if (this.rows[id] && this.rows[id].obj) {
      $(this.rows[id].obj).removeClass('selected').addClass('unfocused');
@@ -430,8 +434,7 @@
expand: function(row)
{
  var depth, new_row;
  var last_expanded_parent_depth;
  var r, p, depth, new_row, last_expanded_parent_depth;
  if (row) {
    row.expanded = true;
@@ -449,13 +452,13 @@
  while (new_row) {
    if (new_row.nodeType == 1) {
      var r = this.rows[new_row.uid];
      r = this.rows[new_row.uid];
      if (r) {
        if (row && (!r.depth || r.depth <= depth))
          break;
        if (r.parent_uid) {
          var p = this.rows[r.parent_uid];
          p = this.rows[r.parent_uid];
          if (p && p.expanded) {
            if ((row && p == row) || last_expanded_parent_depth >= p.depth - 1) {
              last_expanded_parent_depth = p.depth;
@@ -696,9 +699,10 @@
 */
select_next: function()
{
  var next_row = this.get_next_row();
  var prev_row = this.get_prev_row();
  var new_row = (next_row) ? next_row : prev_row;
  var next_row = this.get_next_row(),
    prev_row = this.get_prev_row(),
    new_row = (next_row) ? next_row : prev_row;
  if (new_row)
    this.select_row(new_row.uid, false, false);
},
@@ -710,13 +714,16 @@
select_first: function(mod_key)
{
  var row = this.get_first_row();
  if (row && mod_key) {
    this.shift_select(row, mod_key);
    this.triggerEvent('select');
    this.scrollto(row);
  if (row) {
    if (mod_key) {
      this.shift_select(row, mod_key);
      this.triggerEvent('select');
      this.scrollto(row);
    }
    else {
      this.select(row);
    }
  }
  else if (row)
    this.select(row);
},
@@ -726,13 +733,16 @@
select_last: function(mod_key)
{
  var row = this.get_last_row();
  if (row && mod_key) {
    this.shift_select(row, mod_key);
    this.triggerEvent('select');
    this.scrollto(row);
  if (row) {
    if (mod_key) {
      this.shift_select(row, mod_key);
      this.triggerEvent('select');
      this.scrollto(row);
    }
    else {
      this.select(row);
    }
  }
  else if (row)
    this.select(row);
},
@@ -744,8 +754,9 @@
  if (!this.rows[uid] || !this.rows[uid].has_children)
    return;
  var depth = this.rows[uid].depth;
  var row = this.rows[uid].obj.nextSibling;
  var depth = this.rows[uid].depth,
    row = this.rows[uid].obj.nextSibling;
  while (row) {
    if (row.nodeType == 1) {
      if ((r = this.rows[row.uid])) {
@@ -768,20 +779,20 @@
  if (!this.rows[this.shift_start] || !this.selection.length)
    this.shift_start = id;
  var from_rowIndex = this.rows[this.shift_start].obj.rowIndex,
  var n, from_rowIndex = this.rows[this.shift_start].obj.rowIndex,
    to_rowIndex = this.rows[id].obj.rowIndex,
    i = ((from_rowIndex < to_rowIndex)? from_rowIndex : to_rowIndex),
    j = ((from_rowIndex > to_rowIndex)? from_rowIndex : to_rowIndex);
  // iterate through the entire message list
  for (var n in this.rows) {
  for (n in this.rows) {
    if (this.rows[n].obj.rowIndex >= i && this.rows[n].obj.rowIndex <= j) {
      if (!this.in_selection(n)) {
        this.highlight_row(n, true);
      }
    }
    else {
      if  (this.in_selection(n) && !control) {
      if (this.in_selection(n) && !control) {
        this.highlight_row(n, true);
      }
    }
@@ -794,7 +805,7 @@
 */
in_selection: function(id)
{
  for(var n in this.selection)
  for (var n in this.selection)
    if (this.selection[n]==id)
      return true;
@@ -811,10 +822,10 @@
    return false;
  // reset but remember selection first
  var select_before = this.selection.join(',');
  var n, select_before = this.selection.join(',');
  this.selection = [];
  for (var n in this.rows) {
  for (n in this.rows) {
    if (!filter || this.rows[n][filter] == true) {
      this.last_selected = n;
      this.highlight_row(n, true);
@@ -843,9 +854,9 @@
    return false;
  // remember old selection
  var select_before = this.selection.join(',');
  var n, select_before = this.selection.join(',');
  for (var n in this.rows)
  for (n in this.rows)
    this.highlight_row(n, true);
  // trigger event if selection changed
@@ -863,11 +874,11 @@
 */
clear_selection: function(id)
{
  var num_select = this.selection.length;
  var n, num_select = this.selection.length;
  // one row
  if (id) {
    for (var n in this.selection)
    for (n in this.selection)
      if (this.selection[n] == id) {
        this.selection.splice(n,1);
        break;
@@ -875,7 +886,7 @@
  }
  // all rows
  else {
    for (var n in this.selection)
    for (n in this.selection)
      if (this.rows[this.selection[n]]) {
        $(this.rows[this.selection[n]].obj).removeClass('selected').removeClass('unfocused');
      }
@@ -927,9 +938,10 @@
      $(this.rows[id].obj).addClass('selected');
    }
    else { // unselect row
      var p = $.inArray(id, this.selection);
      var a_pre = this.selection.slice(0, p);
      var a_post = this.selection.slice(p+1, this.selection.length);
      var p = $.inArray(id, this.selection),
        a_pre = this.selection.slice(0, p),
        a_post = this.selection.slice(p+1, this.selection.length);
      this.selection = a_pre.concat(a_post);
      $(this.rows[id].obj).removeClass('selected').removeClass('unfocused');
    }
@@ -945,8 +957,8 @@
  if (this.focused != true)
    return true;
  var keyCode = rcube_event.get_keycode(e);
  var mod_key = rcube_event.get_modifier(e);
  var keyCode = rcube_event.get_keycode(e),
    mod_key = rcube_event.get_modifier(e);
  switch (keyCode) {
    case 40:
@@ -1371,7 +1383,7 @@
 */
column_replace: function(from, to)
{
  var cells = this.list.tHead.rows[0].cells,
  var len, cells = this.list.tHead.rows[0].cells,
    elem = cells[from],
    before = cells[to],
    td = document.createElement('td');
@@ -1384,7 +1396,7 @@
  cells[0].parentNode.replaceChild(elem, td);
  // replace list cells
  for (r=0; r<this.list.tBodies[0].rows.length; r++) {
  for (r=0, len=this.list.tBodies[0].rows.length; r<len; r++) {
    row = this.list.tBodies[0].rows[r];
    elem = row.cells[from];
program/lib/Net/SMTP.php
@@ -106,6 +106,14 @@
    var $_socket = null;
    /**
     * Array of socket options that will be passed to Net_Socket::connect().
     * @see stream_context_create()
     * @var array
     * @access private
     */
    var $_socket_options = null;
    /**
     * The socket I/O timeout value in seconds.
     * @var int
     * @access private
@@ -156,12 +164,13 @@
     * @param string  $localhost  The value to give when sending EHLO or HELO.
     * @param boolean $pipeling   Use SMTP command pipelining
     * @param integer $timeout    Socket I/O timeout in seconds.
     * @param array   $socket_options Socket stream_context_create() options.
     *
     * @access  public
     * @since   1.0
     */
    function Net_SMTP($host = null, $port = null, $localhost = null,
        $pipelining = false, $timeout = 0)
        $pipelining = false, $timeout = 0, $socket_options = null)
    {
        if (isset($host)) {
            $this->host = $host;
@@ -175,6 +184,7 @@
        $this->pipelining = $pipelining;
        $this->_socket = new Net_Socket();
        $this->_socket_options = $socket_options;
        $this->_timeout = $timeout;
        /* Include the Auth_SASL package.  If the package is not
@@ -405,7 +415,8 @@
    {
        $this->_greeting = null;
        $result = $this->_socket->connect($this->host, $this->port,
                                          $persistent, $timeout);
                                          $persistent, $timeout,
                                          $this->_socket_options);
        if (PEAR::isError($result)) {
            return PEAR::raiseError('Failed to connect socket: ' .
                                    $result->getMessage());
@@ -417,8 +428,10 @@
         * timeout values for the initial connection (our $timeout parameter) 
         * and all other socket operations.
         */
        if (PEAR::isError($error = $this->setTimeout($this->_timeout))) {
            return $error;
        if ($this->_timeout > 0) {
            if (PEAR::isError($error = $this->setTimeout($this->_timeout))) {
                return $error;
            }
        }
        if (PEAR::isError($error = $this->_parseResponse(220))) {
program/localization/de_CH/messages.inc
@@ -135,7 +135,7 @@
$messages['nametoolong'] = 'Der Name ist zu lang';
$messages['folderupdated'] = 'Der Ordner wurde erfolgreich aktualisiert';
$messages['foldercreated'] = 'Der Ordner wurde erfolgreich erstellt';
$messages['errorreadonly'] = 'Die Aktion nicht ausgeführt werden. Der Ordner ist schreibgeschützt.';
$messages['errornoperm'] = 'Die Aktion nicht ausgeführt werden. Zugriff verweigert.';
$messages['errorreadonly'] = 'Die Aktion kann nicht ausgeführt werden. Der Ordner ist schreibgeschützt.';
$messages['errornoperm'] = 'Die Aktion kann nicht ausgeführt werden. Zugriff verweigert.';
?>
program/localization/de_DE/messages.inc
@@ -24,8 +24,8 @@
$messages['imaperror'] = 'Keine Verbindung zum IMAP-Server';
$messages['servererror'] = 'Serverfehler!';
$messages['servererrormsg'] = 'Serverfehler: $msg';
$messages['errorreadonly'] = 'Die Aktion nicht ausgeführt werden. Der Ordner ist schreibgeschützt.';
$messages['errornoperm'] = 'Die Aktion nicht ausgeführt werden. Zugriff verweigert.';
$messages['errorreadonly'] = 'Die Aktion kann nicht ausgeführt werden. Der Ordner ist schreibgeschützt.';
$messages['errornoperm'] = 'Die Aktion kann nicht ausgeführt werden. Zugriff verweigert.';
$messages['invalidrequest'] = 'Ungültige Anfrage! Es wurden keine Daten gespeichert.';
$messages['nomessagesfound'] = 'Keine Nachrichten in diesem Ordner';
$messages['loggedout'] = 'Sie haben Ihre Session erfolgreich beendet. Auf Wiedersehen!';
@@ -117,7 +117,7 @@
$messages['smtpfromerror'] = 'SMTP Fehler ($code): Der Absender "$from" konnte nicht gesetzt werden ($msg)';
$messages['smtptoerror'] = 'SMTP Fehler ($code): Der Empfänger "$to" konnte nicht gesetzt werden ($msg)';
$messages['smtprecipientserror'] = 'SMTP Fehler: Die Empfängerliste konnte nicht verarbeitet werden';
$messages['smtpdsnerror'] = 'SMTP-Fehler: Empfangsbestätigung werden nicht unterstützt';
$messages['smtpdsnerror'] = 'SMTP-Fehler: Empfangsbestätigungen werden nicht unterstützt';
$messages['smtperror'] = 'SMTP Fehler: $msg';
$messages['emailformaterror'] = 'Ungültige E-Mail-Adresse: $email';
$messages['toomanyrecipients'] = 'Zuviele Empfänger. Reduzieren Sie die Anzahl Empfängeradressen auf $max.';
program/localization/index.inc
@@ -32,7 +32,7 @@
  'az_AZ' => 'Azerbaijani (Azərbaycanca)',
  'eu_ES' => 'Basque (Euskara)',
  'bn_BD' => 'Bengali (বাংলা)',
  'bs_BA' => 'Bosnian (Bošnjački)',
  'bs_BA' => 'Bosnian (Bosanski)',
  'br'      => 'Breton (Brezhoneg)',
  'bg_BG' => 'Bulgarian (Български)',
  'ca_ES' => 'Catalan (Català)',