diff options
-rw-r--r-- | CHANGELOG | 5 | ||||
-rw-r--r-- | index.php | 4 | ||||
-rw-r--r-- | program/include/rcube_vcard.php | 54 | ||||
-rw-r--r-- | program/js/app.js | 73 | ||||
-rw-r--r-- | program/steps/mail/sendmail.inc | 20 | ||||
-rw-r--r-- | tests/vcards.php | 2 |
6 files changed, 102 insertions, 56 deletions
@@ -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) @@ -119,6 +119,10 @@ if ($RCMAIL->task == 'login' && $RCMAIL->action == 'login') { // 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 diff --git a/program/include/rcube_vcard.php b/program/include/rcube_vcard.php index 283da1db7..9929d0f6d 100644 --- a/program/include/rcube_vcard.php +++ b/program/include/rcube_vcard.php @@ -292,11 +292,10 @@ class rcube_vcard 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 @@ class rcube_vcard 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 { + $lc_key = strtolower($key); + $entry[$lc_key] = array_merge((array)$entry[$lc_key], (array)self::vcard_unquote($value, ',')); } - else - $entry[strtolower($key)] = array_merge((array)$entry[strtolower($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 + } + } + + // 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'); } - $entry = array_merge($entry, (array)self::vcard_unquote($line[2])); + 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 @@ class rcube_vcard return quoted_printable_decode($value); case 'base64': + case 'b': self::$values_decoded = true; return base64_decode($value); @@ -624,13 +643,20 @@ class rcube_vcard 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, ','); } } } diff --git a/program/js/app.js b/program/js/app.js index 28146392f..0db174625 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -269,7 +269,7 @@ function rcube_webmail() // 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() // 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() // 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 @@ function rcube_webmail() // 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() // 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() { 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() 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 @@ function rcube_webmail() } // 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 @@ function rcube_webmail() } if (timeout > 0) - window.setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout); + setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout); return id; }; diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 25eb0596e..b5d383422 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -688,17 +688,19 @@ if ($store_target) { 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'); } } diff --git a/tests/vcards.php b/tests/vcards.php index ba5ce2bef..22f7cdd33 100644 --- a/tests/vcards.php +++ b/tests/vcards.php @@ -44,7 +44,7 @@ class rcube_test_vcards extends UnitTestCase $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"); |