alecpl
2012-04-27 77799d87ba05a8e96d604693dcfa003b5835fe2b
- Applied some fixes from trunk


6 files modified
158 ■■■■■ changed files
CHANGELOG 5 ●●●●● patch | view | raw | blame | history
index.php 4 ●●●● patch | view | raw | blame | history
program/include/rcube_vcard.php 54 ●●●● patch | view | raw | blame | history
program/js/app.js 73 ●●●●● patch | view | raw | blame | history
program/steps/mail/sendmail.inc 20 ●●●●● patch | view | raw | blame | history
tests/vcards.php 2 ●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,11 @@
CHANGELOG Roundcube Webmail
===========================
- Fix redirect to mail/compose on re-login (#1488226)
- Add IE8 hack for messages list issue (#1487821)
- Fix handling errors on draft auto-save
- Fix importing vCard photo with ENCODING param specified (#1488432)
- Fix issue where draft auto-save wasn't executed after some inactivity time
- Fix lack of warning when switching task in compose window (#1488399)
- Fix bug where it wasn't possible to enter ( or & characters in autocomplete fields
- Fix counting of messages search results (on refresh when search filter is in use)
index.php
@@ -119,6 +119,10 @@
      // prevent endless looping on login page
      if ($query['_task'] == 'login')
        unset($query['_task']);
      // prevent redirect to compose with specified ID (#1488226)
      if ($query['_action'] == 'compose' && !empty($query['_id']))
        $query = array();
    }
    // allow plugins to control the redirect url after login success
program/include/rcube_vcard.php
@@ -292,11 +292,10 @@
      case 'photo':
        if (strpos($value, 'http:') === 0) {
            // TODO: fetch file from URL and save it locally?
            $this->raw['PHOTO'][0] = array(0 => $value, 'URL' => true);
            $this->raw['PHOTO'][0] = array(0 => $value, 'url' => true);
        }
        else {
            $encoded = !preg_match('![^a-z0-9/=+-]!i', $value);
            $this->raw['PHOTO'][0] = array(0 => $encoded ? $value : base64_encode($value), 'BASE64' => true);
            $this->raw['PHOTO'][0] = array(0 => $value, 'base64' => (bool) preg_match('![^a-z0-9/=+-]!i', $value));
        }
        break;
@@ -549,26 +548,45 @@
      if (preg_match_all('/([^\\;]+);?/', $line[1], $regs2)) {
        $entry = array();
        $field = strtoupper($regs2[1][0]);
        $enc   = null;
        foreach($regs2[1] as $attrid => $attr) {
          if ((list($key, $value) = explode('=', $attr)) && $value) {
            $value = trim($value);
            if ($key == 'ENCODING') {
              // add next line(s) to value string if QP line end detected
              while ($value == 'QUOTED-PRINTABLE' && preg_match('/=$/', $lines[$i]))
              if ($value == 'QUOTED-PRINTABLE') {
                while (preg_match('/=$/', $lines[$i]))
                  $line[2] .= "\n" . $lines[++$i];
              $line[2] = self::decode_value($line[2], $value);
              }
              $enc = $value;
            }
            else
              $entry[strtolower($key)] = array_merge((array)$entry[strtolower($key)], (array)self::vcard_unquote($value, ','));
            else {
              $lc_key = strtolower($key);
              $entry[$lc_key] = array_merge((array)$entry[$lc_key], (array)self::vcard_unquote($value, ','));
            }
          }
          else if ($attrid > 0) {
            $entry[$key] = true;  // true means attr without =value
            $entry[strtolower($key)] = true;  // true means attr without =value
          }
        }
        $entry = array_merge($entry, (array)self::vcard_unquote($line[2]));
        // decode value
        if ($enc || !empty($entry['base64'])) {
          // save encoding type (#1488432)
          if ($enc == 'B') {
            $entry['encoding'] = 'B';
            // should we use vCard 3.0 instead?
            // $entry['base64'] = true;
          }
          $line[2] = self::decode_value($line[2], $enc ? $enc : 'base64');
        }
        if ($enc != 'B' && empty($entry['base64'])) {
          $line[2] = self::vcard_unquote($line[2]);
        }
        $entry = array_merge($entry, (array) $line[2]);
        $data[$field][] = $entry;
      }
    }
@@ -593,6 +611,7 @@
        return quoted_printable_decode($value);
      case 'base64':
      case 'b':
        self::$values_decoded = true;
        return base64_decode($value);
@@ -624,13 +643,20 @@
        if (is_array($entry)) {
          $value = array();
          foreach($entry as $attrname => $attrvalues) {
            if (is_int($attrname))
            if (is_int($attrname)) {
              if (!empty($entry['base64']) || $entry['encoding'] == 'B') {
                $attrvalues = base64_encode($attrvalues);
              }
              $value[] = $attrvalues;
            elseif ($attrvalues === true)
              $attr .= ";$attrname";    // true means just tag, not tag=value, as in PHOTO;BASE64:...
            }
            else if (is_bool($attrvalues)) {
              if ($attrvalues) {
                $attr .= strtoupper(";$attrname");    // true means just tag, not tag=value, as in PHOTO;BASE64:...
              }
            }
            else {
              foreach((array)$attrvalues as $attrvalue)
                $attr .= ";$attrname=" . self::vcard_quote($attrvalue, ',');
                $attr .= strtoupper(";$attrname=") . self::vcard_quote($attrvalue, ',');
            }
          }
        }
program/js/app.js
@@ -269,7 +269,7 @@
        // show printing dialog
        else if (this.env.action == 'print' && this.env.uid)
          if (bw.safari)
            window.setTimeout('window.print()', 10);
            setTimeout('window.print()', 10);
          else
            window.print();
@@ -746,7 +746,7 @@
      case 'always-load':
        if (this.env.uid && this.env.sender) {
          this.add_contact(urlencode(this.env.sender));
          window.setTimeout(function(){ ref.command('load-images'); }, 300);
          setTimeout(function(){ ref.command('load-images'); }, 300);
          break;
        }
@@ -764,7 +764,7 @@
            qstring += '&_safe=1';
          this.attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', 'rcubemailattachment');
          if (this.attachment_win) {
            window.setTimeout(function(){ ref.attachment_win.focus(); }, 10);
            setTimeout(function(){ ref.attachment_win.focus(); }, 10);
            break;
          }
        }
@@ -879,19 +879,25 @@
        break;
      case 'savedraft':
        var form = this.gui_objects.messageform, msgid;
        // Reset the auto-save timer
        self.clearTimeout(this.save_timer);
        clearTimeout(this.save_timer);
        if (!this.gui_objects.messageform)
        // saving Drafts is disabled
        if (!form)
          break;
        // if saving Drafts is disabled in main.inc.php
        // or if compose form did not change
        if (!this.env.drafts_mailbox || this.cmp_hash == this.compose_field_hash())
        // compose form did not change
        if (this.cmp_hash == this.compose_field_hash()) {
          this.auto_save_start();
          break;
        }
        var form = this.gui_objects.messageform,
          msgid = this.set_busy(true, 'savingmessage');
        // re-set keep-alive timeout
        this.start_keepalive();
        msgid = this.set_busy(true, 'savingmessage');
        form.target = "savetarget";
        form._draft.value = '1';
@@ -907,7 +913,7 @@
          break;
        // Reset the auto-save timer
        self.clearTimeout(this.save_timer);
        clearTimeout(this.save_timer);
        // all checks passed, send message
        var lang = this.spellcheck_lang(),
@@ -926,7 +932,7 @@
      case 'send-attachment':
        // Reset the auto-save timer
        self.clearTimeout(this.save_timer);
        clearTimeout(this.save_timer);
        this.upload_file(props)
        break;
@@ -964,7 +970,7 @@
        if (uid = this.get_single_uid()) {
          ref.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''));
          if (this.printwin) {
            window.setTimeout(function(){ ref.printwin.focus(); }, 20);
            setTimeout(function(){ ref.printwin.focus(); }, 20);
            if (this.env.action != 'show')
              this.mark_message('read', uid);
          }
@@ -975,7 +981,7 @@
        if (uid = this.get_single_uid()) {
          ref.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox));
          if (this.sourcewin)
            window.setTimeout(function(){ ref.sourcewin.focus(); }, 20);
            setTimeout(function(){ ref.sourcewin.focus(); }, 20);
          }
        break;
@@ -1120,7 +1126,7 @@
    // set timer for requests
    if (a && this.env.request_timeout)
      this.request_timer = window.setTimeout(function(){ ref.request_timed_out(); }, this.env.request_timeout * 1000);
      this.request_timer = setTimeout(function(){ ref.request_timed_out(); }, this.env.request_timeout * 1000);
    return id;
  };
@@ -1172,7 +1178,7 @@
    if (this.is_framed())
      parent.rcmail.reload(delay);
    else if (delay)
      window.setTimeout(function(){ rcmail.reload(); }, delay);
      setTimeout(function(){ rcmail.reload(); }, delay);
    else if (window.location)
      location.href = this.env.comm_path + (this.env.action ? '&_action='+this.env.action : '');
  };
@@ -1305,7 +1311,7 @@
    this.env.last_folder_target = null;
    if (this.folder_auto_timer) {
      window.clearTimeout(this.folder_auto_timer);
      clearTimeout(this.folder_auto_timer);
      this.folder_auto_timer = null;
      this.folder_auto_expand = null;
    }
@@ -1358,15 +1364,15 @@
            // if the folder is collapsed, expand it after 1sec and restart the drag & drop process.
            if (div.hasClass('collapsed')) {
              if (this.folder_auto_timer)
                window.clearTimeout(this.folder_auto_timer);
                clearTimeout(this.folder_auto_timer);
              this.folder_auto_expand = this.env.mailboxes[k].id;
              this.folder_auto_timer = window.setTimeout(function() {
              this.folder_auto_timer = setTimeout(function() {
                rcmail.command('collapse-folder', rcmail.folder_auto_expand);
                rcmail.drag_start(null);
              }, 1000);
            } else if (this.folder_auto_timer) {
              window.clearTimeout(this.folder_auto_timer);
              clearTimeout(this.folder_auto_timer);
              this.folder_auto_timer = null;
              this.folder_auto_expand = null;
            }
@@ -1518,7 +1524,7 @@
    // start timer for message preview (wait for double click)
    if (selected && this.env.contentframe && !list.multi_selecting && !this.dummy_select)
      this.preview_timer = window.setTimeout(function(){ ref.msglist_get_preview(); }, 200);
      this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, 200);
    else if (this.env.contentframe)
      this.show_contentframe(false);
  };
@@ -1535,7 +1541,7 @@
          clearTimeout(this.preview_timer);
        if (this.preview_read_timer)
          clearTimeout(this.preview_read_timer);
        this.preview_timer = window.setTimeout(function(){ ref.msglist_get_preview(); }, 200);
        this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, 200);
      }
    }
  };
@@ -1804,8 +1810,11 @@
      else if (c == 'threads')
        html = expando;
      else if (c == 'subject') {
        if (bw.ie)
        if (bw.ie) {
          col.onmouseover = function() { rcube_webmail.long_subject_title_ie(this, message.depth+1); };
          if (bw.ie8)
            tree = '<span></span>' + tree; // #1487821
        }
        html = tree + cols[c];
      }
      else if (c == 'priority') {
@@ -1916,7 +1925,7 @@
      // mark as read and change mbox unread counter
      if (action == 'preview' && this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read >= 0) {
        this.preview_read_timer = window.setTimeout(function() {
        this.preview_read_timer = setTimeout(function() {
          ref.set_message(id, 'unread', false);
          ref.update_thread_root(id, 'read');
          if (ref.env.unread_counts[ref.env.mailbox]) {
@@ -3131,7 +3140,7 @@
  this.auto_save_start = function()
  {
    if (this.env.draft_autosave)
      this.save_timer = self.setTimeout(function(){ ref.command("savedraft"); }, this.env.draft_autosave * 1000);
      this.save_timer = setTimeout(function(){ ref.command("savedraft"); }, this.env.draft_autosave * 1000);
    // Unlock interface now that saving is complete
    this.busy = false;
@@ -3415,7 +3424,7 @@
  this.upload_progress_start = function(action, name)
  {
    window.setTimeout(function() { rcmail.http_request(action, {_progress: name}); },
    setTimeout(function() { rcmail.http_request(action, {_progress: name}); },
      this.env.upload_progress_time * 1000);
  };
@@ -3515,7 +3524,7 @@
  {
    this.display_message(msg, type);
    // before redirect we need to wait some time for Chrome (#1486177)
    window.setTimeout(function(){ ref.list_mailbox(); }, 500);
    setTimeout(function(){ ref.list_mailbox(); }, 500);
  };
@@ -3573,11 +3582,11 @@
      case 37:  // left
      case 39:  // right
        if (mod != SHIFT_KEY)
          return;
          return;
    }
    // start timer
    this.ksearch_timer = window.setTimeout(function(){ ref.ksearch_get_results(props); }, 200);
    this.ksearch_timer = setTimeout(function(){ ref.ksearch_get_results(props); }, 200);
    this.ksearch_input = obj;
    return true;
@@ -3885,7 +3894,7 @@
      source = this.env.source ? this.env.address_sources[this.env.source] : null;
    if (id = list.get_single_selection())
      this.preview_timer = window.setTimeout(function(){ ref.load_contact(id, 'show'); }, 200);
      this.preview_timer = setTimeout(function(){ ref.load_contact(id, 'show'); }, 200);
    else if (this.env.contentframe)
      this.show_contentframe(false);
@@ -5374,7 +5383,7 @@
      }
      // add element and set timeout
      this.messages[key].elements.push(id);
      window.setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout);
      setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout);
      return id;
    }
@@ -5392,7 +5401,7 @@
    }
    if (timeout > 0)
      window.setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout);
      setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout);
    return id;
  };
program/steps/mail/sendmail.inc
@@ -688,17 +688,19 @@
      unlink($mailbody_file);
      $mailbody_file = null;
    }
  }
    // raise error if saving failed
    if (!$saved) {
      raise_error(array('code' => 800, 'type' => 'imap',
        'file' => __FILE__, 'line' => __LINE__,
            'message' => "Could not save message in $store_target"), TRUE, FALSE);
  // raise error if saving failed
  if (!$saved) {
    raise_error(array('code' => 800, 'type' => 'imap',
       'file' => __FILE__, 'line' => __LINE__,
       'message' => "Could not save message in $store_target"), TRUE, FALSE);
      if ($savedraft) {
        $OUTPUT->show_message('errorsaving', 'error');
        $OUTPUT->send('iframe');
      }
    if ($savedraft) {
      $OUTPUT->show_message('errorsaving', 'error');
      // start the auto-save timer again
      $OUTPUT->command('auto_save_start');
      $OUTPUT->send('iframe');
    }
  }
tests/vcards.php
@@ -44,7 +44,7 @@
    $input .= file_get_contents($this->_srcpath('johndoe.vcf'));
    
    $vcards = rcube_vcard::import($input);
    $this->assertEqual(2, count($vcards), "Detected 2 vcards");
    $this->assertEqual("Apple Computer AG", $vcards[0]->displayname, "FN => displayname");
    $this->assertEqual("John DoĆ«", $vcards[1]->displayname, "Displayname with correct charset");