alecpl
2011-11-25 e0960f6365b4b0af314d955847b9422067c83eb2
- Prevent from memory_limit exceeding when trying to parse big messages bodies (#1487424):
don't try to parse it, display notice with a link to download it directly


8 files modified
78 ■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
program/include/main.inc 15 ●●●●● patch | view | raw | blame | history
program/localization/en_US/labels.inc 1 ●●●● patch | view | raw | blame | history
program/localization/en_US/messages.inc 1 ●●●● patch | view | raw | blame | history
program/steps/mail/func.inc 27 ●●●● patch | view | raw | blame | history
program/steps/mail/get.inc 18 ●●●● patch | view | raw | blame | history
skins/default/common.css 1 ●●●● patch | view | raw | blame | history
skins/default/mail.css 14 ●●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Prevent from memory_limit exceeding when trying to parse big messages bodies (#1487424)
- Add possibility to add SASL mechanisms for SMTP in smtp_connect hook (#1487937)
- Mark (with different color) folders with recent messages (#1486234)
- Fix possible infinite redirect on attachment preview (#1488199)
program/include/main.inc
@@ -1846,6 +1846,21 @@
/**
 * Check if we can process not exceeding memory_limit
 *
 * @param integer Required amount of memory
 * @return boolean
 */
function rcmail_mem_check($need)
{
  $mem_limit = parse_bytes(ini_get('memory_limit'));
  $memory    = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
  return $mem_limit && $memory + $need > $mem_limit ? false : true;
}
/**
 * Check if working in SSL mode
 *
 * @param integer HTTPS port number
program/localization/en_US/labels.inc
@@ -152,7 +152,6 @@
$labels['deleted'] = 'Deleted';
$labels['invert'] = 'Invert';
$labels['filter'] = 'Filter';
$labels['list'] = 'List';
$labels['threads'] = 'Threads';
$labels['expand-all'] = 'Expand All';
program/localization/en_US/messages.inc
@@ -157,5 +157,6 @@
$messages['invalidimageformat'] = 'Not a valid image format.';
$messages['mispellingsfound'] = 'Spelling errors detected in the message.';
$messages['parentnotwritable'] = 'Unable to create/move folder into selected parent folder. No access rights.';
$messages['messagetoobig'] = 'The message part is too big to process it.';
?>
program/steps/mail/func.inc
@@ -989,14 +989,20 @@
    if (preg_match('/^headertable([a-z]+)$/i', $attr, $regs))
      $header_attrib[$regs[1]] = $value;
  if (!empty($MESSAGE->parts))
    {
    foreach ($MESSAGE->parts as $i => $part)
      {
  if (!empty($MESSAGE->parts)) {
    foreach ($MESSAGE->parts as $i => $part) {
      if ($part->type == 'headers')
        $out .= rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : NULL, $part->headers);
      else if ($part->type == 'content' && $part->size)
        {
      else if ($part->type == 'content' && $part->size) {
        // Check if we have enough memory to handle the message in it
        // #1487424: we need up to 10x more memory than the body
        if (!rcmail_mem_check($part->size * 10)) {
          $out .= html::span('part-notice', rcube_label('messagetoobig'). ' '
            . html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part='.$part->mime_id
              .'&_mbox='. urlencode($IMAP->get_mailbox_name()), rcube_label('download')));
          continue;
        }
        if (empty($part->ctype_parameters) || empty($part->ctype_parameters['charset']))
          $part->ctype_parameters['charset'] = $MESSAGE->headers->charset;
@@ -1034,12 +1040,21 @@
      }
    }
  else {
    // Check if we have enough memory to handle the message in it
    // #1487424: we need up to 10x more memory than the body
    if (!rcmail_mem_check(strlen($MESSAGE->body) * 10)) {
      $out .= html::span('part-notice', rcube_label('messagetoobig'). ' '
        . html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part=0'
          .'&_mbox='. urlencode($IMAP->get_mailbox_name()), rcube_label('download')));
    }
    else {
    $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
      'part' => $MESSAGE, 'prefix' => ''));
    $out .= html::div('message-part', $plugin['prefix'] . html::tag('pre', array(),
      rcmail_plain_body(Q($MESSAGE->body, 'strict', false))));
    }
  }
  // list images after mail body
  if ($CONFIG['inline_images'] && !empty($MESSAGE->attachments)) {
program/steps/mail/get.inc
@@ -70,7 +70,7 @@
  exit;
}
else if ($pid = get_input_value('_part', RCUBE_INPUT_GET)) {
else if (strlen($pid = get_input_value('_part', RCUBE_INPUT_GET))) {
  if ($part = $MESSAGE->mime_parts[$pid]) {
    $ctype_primary = strtolower($part->ctype_primary);
@@ -109,18 +109,30 @@
    // deliver part content
    if ($ctype_primary == 'text' && $ctype_secondary == 'html' && empty($plugin['download'])) {
      // Check if we have enough memory to handle the message in it
      // #1487424: we need up to 10x more memory than the body
      if (!rcmail_mem_check($part->size * 10)) {
        $out = '<body>' . rcube_label('messagetoobig'). ' '
          . html::a('?_task=mail&_action=get&_download=1&_uid='.$MESSAGE->uid.'&_part='.$part->mime_id
            .'&_mbox='. urlencode($IMAP->get_mailbox_name()), rcube_label('download')) . '</body></html>';
      }
      else {
      // get part body if not available
      if (!$part->body)
        $part->body = $MESSAGE->get_part_content($part->mime_id);
        $out = rcmail_print_body($part, array('safe' => $MESSAGE->is_safe, 'inline_html' => false));
      }
      $OUTPUT = new rcube_html_page();
      $OUTPUT->write(rcmail_print_body($part, array('safe' => $MESSAGE->is_safe, 'inline_html' => false)));
      $OUTPUT->write($out);
    }
    else {
      // don't kill the connection if download takes more than 30 sec.
      @set_time_limit(0);
      $filename = $part->filename ? $part->filename : ($MESSAGE->subject ? $MESSAGE->subject : 'roundcube') . '.'.$ctype_secondary;
      $ext      = '.' . ($mimetype == 'text/plain' ? 'txt' : $ctype_secondary);
      $filename = $part->filename ? $part->filename : ($MESSAGE->subject ? $MESSAGE->subject : 'roundcube') . $ext;
      $filename = preg_replace('[\r\n]', '', $filename);
      if ($browser->ie && $browser->ver < 7)
skins/default/common.css
@@ -232,6 +232,7 @@
}
#message div.notice,
#messagebody .part-notice,
#message-objects div.notice
{
  background: url(images/display/icons.png) 6px 3px no-repeat;
skins/default/mail.css
@@ -1203,20 +1203,28 @@
  margin: 8px;
}
#message-objects div
#messagebody span.part-notice
{
  display: block;
}
#message-objects div,
#messagebody span.part-notice
{
  margin: 8px;
  min-height: 20px;
  padding: 10px 10px 6px 46px;
}
#message-objects div a
#message-objects div a,
#messagebody span.part-notice a
{
  color: #666666;
  padding-left: 10px;
}
#message-objects div a:hover
#message-objects div a:hover,
#messagebody span.part-notice a:hover
{
  color: #333333;
}