Changeset 77449d0 in github
- Timestamp:
- Nov 28, 2011 4:03:27 AM (18 months ago)
- Branches:
- release-0.7
- Children:
- 230ccba
- Parents:
- 2a3e0276
- Files:
-
- 13 edited
-
CHANGELOG (modified) (1 diff)
-
config/main.inc.php.dist (modified) (1 diff)
-
installer/rcube_install.php (modified) (6 diffs)
-
program/include/main.inc (modified) (5 diffs)
-
program/include/rcube_browser.php (modified) (1 diff)
-
program/include/rcube_config.php (modified) (1 diff)
-
program/include/rcube_smtp.php (modified) (1 diff)
-
program/js/app.js (modified) (1 diff)
-
program/lib/html2text.php (modified) (11 diffs)
-
program/steps/addressbook/func.inc (modified) (1 diff)
-
program/steps/mail/search.inc (modified) (3 diffs)
-
skins/default/functions.js (modified) (6 diffs)
-
tests/mailfunc.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
r3ad2b1b r77449d0 2 2 =========================== 3 3 4 - Use strpos() instead of strstr() when possible (#1488211) 5 - Fix handling HTML entities when converting HTML to text (#1488212) 6 - Fix fit_string_to_size() renders browser and ui unresponsive (#1488207) 7 - Fix handling of invalid characters in request (#1488124) 8 - Fix merging some configuration options in update.sh script (#1485864) 9 - Fix so TEXT key will remove all HEADER keys in IMAP SEARCH (#1488208) 10 - Fix handling contact photo url with https:// prefix (#1488202) 4 11 - Fix possible infinite redirect on attachment preview (#1488199) 5 12 - Improved clickjacking protection for browsers which don't support X-Frame-Options headers -
config/main.inc.php.dist
r3fec695 r77449d0 654 654 $rcmail_config['timezone'] = 'auto'; 655 655 656 // is daylight saving On? 657 $rcmail_config['dst_active'] = (bool)date('I');656 // is daylight saving On? Default: (bool)date('I'); 657 $rcmail_config['dst_active'] = null; 658 658 659 659 // prefer displaying HTML messages -
installer/rcube_install.php
r4348692 r77449d0 143 143 foreach ($this->config as $prop => $default) { 144 144 145 $value = (isset($_POST["_$prop"]) || $this->bool_config_props[$prop]) ? $_POST["_$prop"] : $default; 145 $is_default = !isset($_POST["_$prop"]); 146 $value = !$is_default || $this->bool_config_props[$prop] ? $_POST["_$prop"] : $default; 146 147 147 148 // convert some form data 148 if ($prop == 'debug_level' ) {149 $val = 0;150 if (is_array($value))149 if ($prop == 'debug_level' && !$is_default) { 150 if (is_array($value)) { 151 $val = 0; 151 152 foreach ($value as $dbgval) 152 153 $val += intval($dbgval); 153 $value = $val; 154 $value = $val; 155 } 154 156 } 155 157 else if ($which == 'db' && $prop == 'db_dsnw' && !empty($_POST['_dbtype'])) { 156 158 if ($_POST['_dbtype'] == 'sqlite') 157 159 $value = sprintf('%s://%s?mode=0646', $_POST['_dbtype'], $_POST['_dbname']{0} == '/' ? '/' . $_POST['_dbname'] : $_POST['_dbname']); 158 else 160 else if ($_POST['_dbtype']) 159 161 $value = sprintf('%s://%s:%s@%s/%s', $_POST['_dbtype'], 160 162 rawurlencode($_POST['_dbuser']), rawurlencode($_POST['_dbpass']), $_POST['_dbhost'], $_POST['_dbname']); … … 178 180 } 179 181 else if ($prop == 'default_imap_folders') { 180 $value = Array();182 $value = array(); 181 183 foreach ($this->config['default_imap_folders'] as $_folder) { 182 switch ($_folder) {184 switch ($_folder) { 183 185 case 'Drafts': $_folder = $this->config['drafts_mbox']; break; 184 186 case 'Sent': $_folder = $this->config['sent_mbox']; break; … … 207 209 $out = preg_replace( 208 210 '/(\$rcmail_config\[\''.preg_quote($prop).'\'\])\s+=\s+(.+);/Uie', 209 "'\\1 = ' . rcube_install::_dump_var(\$value ) . ';'",211 "'\\1 = ' . rcube_install::_dump_var(\$value, \$prop) . ';'", 210 212 $out); 211 213 } … … 300 302 $this->config = array(); 301 303 $this->load_defaults(); 302 304 303 305 foreach ($this->replaced_config as $prop => $replacement) { 304 306 if (isset($current[$prop])) { … … 329 331 if ($current['keep_alive'] && $current['session_lifetime'] < $current['keep_alive']) 330 332 $current['session_lifetime'] = max(10, ceil($current['keep_alive'] / 60) * 2); 331 333 332 334 $this->config = array_merge($this->config, $current); 333 335 334 336 foreach ((array)$current['ldap_public'] as $key => $values) { 335 337 $this->config['ldap_public'][$key] = $current['ldap_public'][$key]; … … 615 617 616 618 617 static function _dump_var($var) { 619 static function _dump_var($var, $name=null) { 620 // special values 621 switch ($name) { 622 case 'syslog_facility': 623 $list = array(32 => 'LOG_AUTH', 80 => 'LOG_AUTHPRIV', 72 => ' LOG_CRON', 624 24 => 'LOG_DAEMON', 0 => 'LOG_KERN', 128 => 'LOG_LOCAL0', 625 136 => 'LOG_LOCAL1', 144 => 'LOG_LOCAL2', 152 => 'LOG_LOCAL3', 626 160 => 'LOG_LOCAL4', 168 => 'LOG_LOCAL5', 176 => 'LOG_LOCAL6', 627 184 => 'LOG_LOCAL7', 48 => 'LOG_LPR', 16 => 'LOG_MAIL', 628 56 => 'LOG_NEWS', 40 => 'LOG_SYSLOG', 8 => 'LOG_USER', 64 => 'LOG_UUCP'); 629 if ($val = $list[$var]) 630 return $val; 631 break; 632 } 633 634 618 635 if (is_array($var)) { 619 636 if (empty($var)) { -
program/include/main.inc
r3ad2b1b r77449d0 641 641 { 642 642 $value = NULL; 643 644 if ($source==RCUBE_INPUT_GET && isset($_GET[$fname])) 645 $value = $_GET[$fname]; 646 else if ($source==RCUBE_INPUT_POST && isset($_POST[$fname])) 647 $value = $_POST[$fname]; 648 else if ($source==RCUBE_INPUT_GPC) 649 { 643 644 if ($source == RCUBE_INPUT_GET) { 645 if (isset($_GET[$fname])) 646 $value = $_GET[$fname]; 647 } 648 else if ($source == RCUBE_INPUT_POST) { 649 if (isset($_POST[$fname])) 650 $value = $_POST[$fname]; 651 } 652 else if ($source == RCUBE_INPUT_GPC) { 650 653 if (isset($_POST[$fname])) 651 654 $value = $_POST[$fname]; … … 654 657 else if (isset($_COOKIE[$fname])) 655 658 $value = $_COOKIE[$fname]; 656 }659 } 657 660 658 661 return parse_input_value($value, $allow_html, $charset); … … 662 665 * Parse/validate input value. See get_input_value() 663 666 * Performs stripslashes() and charset conversion if necessary 664 * 667 * 665 668 * @param string Input value 666 669 * @param boolean Allow HTML tags in field value … … 688 691 $value = stripslashes($value); 689 692 690 // remove HTML tags if not allowed 693 // remove HTML tags if not allowed 691 694 if (!$allow_html) 692 695 $value = strip_tags($value); 693 696 697 $output_charset = is_object($OUTPUT) ? $OUTPUT->get_charset() : null; 698 699 // remove invalid characters (#1488124) 700 if ($output_charset == 'UTF-8') 701 $value = rc_utf8_clean($value); 702 694 703 // convert to internal charset 695 if ( is_object($OUTPUT) && $charset)696 return rcube_charset_convert($value, $OUTPUT->get_charset(), $charset);697 else 698 return $value;704 if ($charset && $output_charset) 705 $value = rcube_charset_convert($value, $output_charset, $charset); 706 707 return $value; 699 708 } 700 709 … … 712 721 foreach ($src as $key => $value) { 713 722 $fname = $key[0] == '_' ? substr($key, 1) : $key; 714 if ($ignore && !preg_match( "/($ignore)/", $fname))723 if ($ignore && !preg_match('/^(' . $ignore . ')$/', $fname)) 715 724 $out[$fname] = get_input_value($key, $mode); 716 725 } 717 726 718 727 return $out; 719 728 } -
program/include/rcube_browser.php
rdcf8112 r77449d0 34 34 35 35 $this->ver = 0; 36 $this->win = str str($HTTP_USER_AGENT, 'win');37 $this->mac = str str($HTTP_USER_AGENT, 'mac');38 $this->linux = str str($HTTP_USER_AGENT, 'linux');39 $this->unix = str str($HTTP_USER_AGENT, 'unix');36 $this->win = strpos($HTTP_USER_AGENT, 'win') != false; 37 $this->mac = strpos($HTTP_USER_AGENT, 'mac') != false; 38 $this->linux = strpos($HTTP_USER_AGENT, 'linux') != false; 39 $this->unix = strpos($HTTP_USER_AGENT, 'unix') != false; 40 40 41 $this->opera = str str($HTTP_USER_AGENT, 'opera');42 $this->ns4 = str str($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie');43 $this->ns = ($this->ns4 || str str($HTTP_USER_AGENT, 'netscape'));44 $this->ie = !$this->opera && str istr($HTTP_USER_AGENT, 'compatible; msie');45 $this->mz = !$this->ie && str str($HTTP_USER_AGENT, 'mozilla/5');46 $this->chrome = str str($HTTP_USER_AGENT, 'chrome');47 $this->khtml = str str($HTTP_USER_AGENT, 'khtml');48 $this->safari = !$this->chrome && ($this->khtml || str str($HTTP_USER_AGENT, 'safari'));41 $this->opera = strpos($HTTP_USER_AGENT, 'opera') !== false; 42 $this->ns4 = strpos($HTTP_USER_AGENT, 'mozilla/4') !== false && strpos($HTTP_USER_AGENT, 'msie') === false; 43 $this->ns = ($this->ns4 || strpos($HTTP_USER_AGENT, 'netscape') !== false); 44 $this->ie = !$this->opera && strpos($HTTP_USER_AGENT, 'compatible; msie') !== false; 45 $this->mz = !$this->ie && strpos($HTTP_USER_AGENT, 'mozilla/5') !== false; 46 $this->chrome = strpos($HTTP_USER_AGENT, 'chrome') !== false; 47 $this->khtml = strpos($HTTP_USER_AGENT, 'khtml') !== false; 48 $this->safari = !$this->chrome && ($this->khtml || strpos($HTTP_USER_AGENT, 'safari') !== false); 49 49 50 50 if ($this->ns || $this->chrome) { -
program/include/rcube_config.php
rf4f4354f r77449d0 91 91 // enable display_errors in 'show' level, but not for ajax requests 92 92 ini_set('display_errors', intval(empty($_REQUEST['_remote']) && ($this->prop['debug_level'] & 4))); 93 93 94 94 // set timezone auto settings values 95 95 if ($this->prop['timezone'] == 'auto') { 96 96 $this->prop['dst_active'] = intval(date('I')); 97 $this->prop['_timezone_value'] = date('Z') / 3600 - $this->prop['dst_active']; 97 $this->prop['_timezone_value'] = date('Z') / 3600 - $this->prop['dst_active']; 98 } 99 else if ($this->prop['dst_active'] === null) { 100 $this->prop['dst_active'] = intval(date('I')); 98 101 } 99 102 -
program/include/rcube_smtp.php
rfb40f37 r77449d0 382 382 383 383 // Reject envelope From: addresses with spaces. 384 if (str str($from, ' '))384 if (strpos($from, ' ') !== false) 385 385 return false; 386 386 -
program/js/app.js
r3ad2b1b r77449d0 5744 5744 }; 5745 5745 5746 this.plain2html = function(plain Text, id)5746 this.plain2html = function(plain, id) 5747 5747 { 5748 5748 var lock = this.set_busy(true, 'converting'); 5749 $('#'+id).val(plainText ? '<pre>'+plainText+'</pre>' : ''); 5749 5750 plain = plain.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); 5751 $('#'+id).val(plain ? '<pre>'+plain+'</pre>' : ''); 5752 5750 5753 this.set_busy(false, null, lock); 5751 5754 }; -
program/lib/html2text.php
r4d7fbd5 r77449d0 146 146 "/\r/", // Non-legal carriage return 147 147 "/[\n\t]+/", // Newlines and tabs 148 '/[ ]{2,}/', // Runs of spaces, pre-handling149 148 '/<script[^>]*>.*?<\/script>/i', // <script>s -- which strip_tags supposedly has problems with 150 149 '/<style[^>]*>.*?<\/style>/i', // <style>s -- which strip_tags supposedly has problems with … … 162 161 '/(<tr[^>]*>|<\/tr>)/i', // <tr> and </tr> 163 162 '/<td[^>]*>(.*?)<\/td>/i', // <td> and </td> 163 ); 164 165 /** 166 * List of pattern replacements corresponding to patterns searched. 167 * 168 * @var array $replace 169 * @access public 170 * @see $search 171 */ 172 var $replace = array( 173 '', // Non-legal carriage return 174 ' ', // Newlines and tabs 175 '', // <script>s -- which strip_tags supposedly has problems with 176 '', // <style>s -- which strip_tags supposedly has problems with 177 "\n\n", // <P> 178 "\n", // <br> 179 '_\\1_', // <i> 180 '_\\1_', // <em> 181 "\n\n", // <ul> and </ul> 182 "\n\n", // <ol> and </ol> 183 "\t* \\1\n", // <li> and </li> 184 "\n\t* ", // <li> 185 "\n-------------------------\n", // <hr> 186 "<div>\n", // <div> 187 "\n\n", // <table> and </table> 188 "\n", // <tr> and </tr> 189 "\t\t\\1\n", // <td> and </td> 190 ); 191 192 /** 193 * List of preg* regular expression patterns to search for, 194 * used in conjunction with $ent_replace. 195 * 196 * @var array $ent_search 197 * @access public 198 * @see $ent_replace 199 */ 200 var $ent_search = array( 164 201 '/&(nbsp|#160);/i', // Non-breaking space 165 202 '/&(quot|rdquo|ldquo|#8220|#8221|#147|#148);/i', … … 177 214 '/&(euro|#8364);/i', // Euro sign 178 215 '/&(amp|#38);/i', // Ampersand: see _converter() 179 '/[ ]{2,}/' // Runs of spaces, post-handling216 '/[ ]{2,}/', // Runs of spaces, post-handling 180 217 ); 181 218 … … 183 220 * List of pattern replacements corresponding to patterns searched. 184 221 * 185 * @var array $replace 186 * @access public 187 * @see $search 188 */ 189 var $replace = array( 190 '', // Non-legal carriage return 191 ' ', // Newlines and tabs 192 ' ', // Runs of spaces, pre-handling 193 '', // <script>s -- which strip_tags supposedly has problems with 194 '', // <style>s -- which strip_tags supposedly has problems with 195 "\n\n", // <P> 196 "\n", // <br> 197 '_\\1_', // <i> 198 '_\\1_', // <em> 199 "\n\n", // <ul> and </ul> 200 "\n\n", // <ol> and </ol> 201 "\t* \\1\n", // <li> and </li> 202 "\n\t* ", // <li> 203 "\n-------------------------\n", // <hr> 204 "<div>\n", // <div> 205 "\n\n", // <table> and </table> 206 "\n", // <tr> and </tr> 207 "\t\t\\1\n", // <td> and </td> 222 * @var array $ent_replace 223 * @access public 224 * @see $ent_search 225 */ 226 var $ent_replace = array( 208 227 ' ', // Non-breaking space 209 228 '"', // Double quotes … … 220 239 'EUR', // Euro sign. ? 221 240 '|+|amp|+|', // Ampersand: see _converter() 222 ' ' // Runs of spaces, post-handling241 ' ', // Runs of spaces, post-handling 223 242 ); 224 243 … … 304 323 */ 305 324 var $_link_list = ''; 306 325 307 326 /** 308 327 * Number of valid links detected in the text, used for plain text … … 315 334 var $_link_count = 0; 316 335 317 /** 318 * Boolean flag, true if a table of link URLs should be listed after the text. 319 * 320 * @var boolean $_do_links 321 * @access private 322 * @see html2text() 336 /** 337 * Boolean flag, true if a table of link URLs should be listed after the text. 338 * 339 * @var boolean $_do_links 340 * @access private 341 * @see html2text() 323 342 */ 324 343 var $_do_links = true; 325 344 326 345 /** 327 346 * Constructor. … … 493 512 $this->_convert_pre($text); 494 513 495 // Run our defined search-and-replace514 // Run our defined tags search-and-replace 496 515 $text = preg_replace($this->search, $this->replace, $text); 516 517 // Run our defined tags search-and-replace with callback 518 $text = preg_replace_callback($this->callback_search, array('html2text', '_preg_callback'), $text); 519 520 // Strip any other HTML tags 521 $text = strip_tags($text, $this->allowed_tags); 522 523 // Run our defined entities/characters search-and-replace 524 $text = preg_replace($this->ent_search, $this->ent_replace, $text); 497 525 498 526 // Replace known html entities 499 527 $text = html_entity_decode($text, ENT_COMPAT, 'UTF-8'); 500 501 // Run our defined search-and-replace with callback502 $text = preg_replace_callback($this->callback_search, array('html2text', '_preg_callback'), $text);503 528 504 529 // Remove unknown/unhandled entities (this cannot be done in search-and-replace block) … … 509 534 $text = str_replace('|+|amp|+|', '&', $text); 510 535 511 // Strip any other HTML tags512 $text = strip_tags($text, $this->allowed_tags);513 514 536 // Bring down number of empty lines to 2 max 515 537 $text = preg_replace("/\n\s+\n/", "\n\n", $text); … … 517 539 518 540 // remove leading empty lines (can be produced by eg. P tag on the beginning) 519 $text = preg_replace('/^\n+/', '', $text);541 $text = ltrim($text, "\n"); 520 542 521 543 // Wrap the text to a readable format … … 545 567 return $display; 546 568 547 if ( substr($link, 0, 7) == 'http://' || substr($link, 0, 8) == 'https://' || 548 substr($link, 0, 7) == 'mailto:' 549 ) { 569 if ( preg_match('!^(https?://|mailto:)!', $link) ) { 550 570 $this->_link_count++; 551 571 $this->_link_list .= '[' . $this->_link_count . "] $link\n"; -
program/steps/addressbook/func.inc
r51f7a5b r77449d0 706 706 unset($attrib['placeholder']); 707 707 708 if ( strpos($record['photo'], 'http:') === 0)708 if (preg_match('!^https?://!i', $record['photo'])) 709 709 $photo_img = $record['photo']; 710 710 else if ($record['photo']) -
program/steps/mail/search.inc
rb1f0846 r77449d0 32 32 $filter = get_input_value('_filter', RCUBE_INPUT_GET); 33 33 $headers = get_input_value('_headers', RCUBE_INPUT_GET); 34 $subject = array(); 34 35 35 36 $search_request = md5($mbox.$filter.$str); … … 71 72 $subject['text'] = "TEXT"; 72 73 } 73 else if (trim($str))74 else if (strlen(trim($str))) 74 75 { 75 76 if ($headers) { 76 foreach(explode(',', $headers) as $header) 77 switch ($header) { 78 case 'text': $subject['text'] = 'TEXT'; break; 79 default: $subject[$header] = 'HEADER '.strtoupper($header); 77 foreach (explode(',', $headers) as $header) { 78 if ($header == 'text') { 79 // #1488208: get rid of other headers when searching by "TEXT" 80 $subject = array('text' => 'TEXT'); 81 break; 80 82 } 83 else { 84 $subject[$header] = 'HEADER '.strtoupper($header); 85 } 86 } 81 87 82 88 // save search modifiers for the current folder to user prefs … … 90 96 } 91 97 92 $search = $srch? trim($srch) : trim($str);98 $search = isset($srch) ? trim($srch) : trim($str); 93 99 94 if ( $subject) {100 if (!empty($subject)) { 95 101 $search_str .= str_repeat(' OR', count($subject)-1); 96 102 foreach ($subject as $sub) -
skins/default/functions.js
r4b09fb6 r77449d0 193 193 if (show && ref) { 194 194 var pos = $(ref).offset(); 195 obj.css({ left:pos.left, top:(pos.top + ref.offsetHeight + 2)}) 196 .find(':checked').prop('checked', false); 195 obj.css({left:pos.left, top:(pos.top + ref.offsetHeight + 2)}); 197 196 198 197 if (rcmail.env.search_mods) { 199 var n, mbox = rcmail.env.mailbox, mods = rcmail.env.search_mods; 200 201 if (rcmail.env.task != 'addressbook') { 198 var n, all, 199 list = $('input:checkbox[name="s_mods[]"]', obj), 200 mbox = rcmail.env.mailbox, 201 mods = rcmail.env.search_mods; 202 203 if (rcmail.env.task == 'mail') { 202 204 mods = mods[mbox] ? mods[mbox] : mods['*']; 203 205 all = 'text'; 206 } 207 else { 208 all = '*'; 209 } 210 211 if (mods[all]) 212 list.map(function() { 213 this.checked = true; 214 this.disabled = this.value != all; 215 }); 216 else { 217 list.prop('disabled', false).prop('checked', false); 204 218 for (n in mods) 205 219 $('#s_mod_' + n).prop('checked', true); 206 220 } 207 else {208 if (mods['*'])209 $('input:checkbox[name="s_mods[]"]').map(function() {210 this.checked = true;211 this.disabled = this.value != '*';212 });213 else {214 for (n in mods)215 $('#s_mod_' + n).prop('checked', true);216 }217 }218 221 } 219 222 } … … 223 226 set_searchmod: function(elem) 224 227 { 225 var task = rcmail.env.task,228 var all, m, task = rcmail.env.task, 226 229 mods = rcmail.env.search_mods, 227 230 mbox = rcmail.env.mailbox; … … 233 236 if (!mods[mbox]) 234 237 mods[mbox] = rcube_clone_object(mods['*']); 235 if (!elem.checked) 236 delete(mods[mbox][elem.value]); 237 else 238 mods[mbox][elem.value] = 1; 238 m = mods[mbox]; 239 all = 'text'; 239 240 } 240 241 else { //addressbook 241 if (!elem.checked) 242 delete(mods[elem.value]); 243 else 244 mods[elem.value] = 1; 245 246 // mark all fields 247 if (elem.value == '*') { 248 $('input:checkbox[name="s_mods[]"]').map(function() { 249 if (this == elem) 250 return; 251 252 if (elem.checked) { 253 mods[this.value] = 1; 254 this.checked = true; 255 this.disabled = true; 256 } 257 else { 258 this.disabled = false; 259 } 260 }); 261 } 262 } 263 264 rcmail.env.search_mods = mods; 242 m = mods; 243 all = '*'; 244 } 245 246 if (!elem.checked) 247 delete(m[elem.value]); 248 else 249 m[elem.value] = 1; 250 251 // mark all fields 252 if (elem.value != all) 253 return; 254 255 $('input:checkbox[name="s_mods[]"]').map(function() { 256 if (this == elem) 257 return; 258 259 this.checked = true; 260 if (elem.checked) { 261 this.disabled = true; 262 delete m[this.value]; 263 } 264 else { 265 this.disabled = false; 266 m[this.value] = 1; 267 } 268 }); 265 269 }, 266 270 … … 567 571 rcmail.addEventListener('responseaftercheck-recent', rcube_render_mailboxlist); 568 572 rcmail.addEventListener('aftercollapse-folder', rcube_render_mailboxlist); 569 rcube_render_mailboxlist();570 573 } 571 574 … … 589 592 function rcube_render_mailboxlist() 590 593 { 591 if (bw.ie6) // doesn't work well on IE6 594 var list = $('#mailboxlist > li a, #mailboxlist ul:visible > li a'); 595 596 // it's too slow with really big number of folders, especially on IE 597 if (list.length > 500 * (bw.ie ? 0.2 : 1)) 592 598 return; 593 599 594 $('#mailboxlist > li a, #mailboxlist ul:visible > li a').each(function(){ 595 var elem = $(this); 596 var text = elem.data('text'); 600 list.each(function(){ 601 var elem = $(this), 602 text = elem.data('text'); 603 597 604 if (!text) { 598 605 text = elem.text().replace(/\s+\(.+$/, ''); … … 612 619 function fit_string_to_size(str, elem, len) 613 620 { 614 var result = str; 615 var ellip = '...'; 616 var span = $('<b>').css({ visibility:'hidden', padding:'0px' }).appendTo(elem).get(0); 617 618 // on first run, check if string fits into the length already. 619 span.innerHTML = result; 620 if (span.offsetWidth > len) { 621 var cut = Math.max(1, Math.floor(str.length * ((span.offsetWidth - len) / span.offsetWidth) / 2)), 622 mid = Math.floor(str.length / 2); 623 var offLeft = mid, offRight = mid; 624 while (true) { 625 offLeft = mid - cut; 626 offRight = mid + cut; 627 span.innerHTML = str.substring(0,offLeft) + ellip + str.substring(offRight); 628 629 // break loop if string fits size 630 if (span.offsetWidth <= len || offLeft < 3) 631 break; 632 633 cut++; 634 } 635 636 // build resulting string 637 result = str.substring(0,offLeft) + ellip + str.substring(offRight); 638 } 639 640 span.parentNode.removeChild(span); 641 return result; 621 var w, span, result = str, ellip = '...'; 622 623 if (!rcmail.env.tmp_span) { 624 // it should be appended to elem to use the same css style 625 // but for performance reasons we'll append it to body (once) 626 span = $('<b>').css({visibility: 'hidden', padding: '0px'}) 627 .appendTo($('body', document)).get(0); 628 rcmail.env.tmp_span = span; 629 } 630 else { 631 span = rcmail.env.tmp_span; 632 } 633 span.innerHTML = result; 634 635 // on first run, check if string fits into the length already. 636 w = span.offsetWidth; 637 if (w > len) { 638 var cut = Math.max(1, Math.floor(str.length * ((w - len) / w) / 2)), 639 mid = Math.floor(str.length / 2), 640 offLeft = mid, 641 offRight = mid; 642 643 while (true) { 644 offLeft = mid - cut; 645 offRight = mid + cut; 646 span.innerHTML = str.substring(0,offLeft) + ellip + str.substring(offRight); 647 648 // break loop if string fits size 649 if (offLeft < 3 || span.offsetWidth) 650 break; 651 652 cut++; 653 } 654 655 // build resulting string 656 result = str.substring(0,offLeft) + ellip + str.substring(offRight); 657 } 658 659 return result; 642 660 } 643 661 -
tests/mailfunc.php
r3ad2b1b r77449d0 107 107 $washed = rcmail_print_body($part); 108 108 109 $this->assertPattern('/<p> ÃÂÃÅŸÃÅòÃŞû<\/p>/', $washed, "Remove non-unicode characters from HTML message body");109 $this->assertPattern('/<p>ÑОЌвПл<\/p>/', $washed, "Remove non-unicode characters from HTML message body"); 110 110 } 111 111
Note: See TracChangeset
for help on using the changeset viewer.
