alecpl
2008-04-15 d7a411f099596cbc8e749e1f0802ac2bb2c6289e
program/steps/mail/func.inc
@@ -19,7 +19,6 @@
*/
require_once('lib/html2text.inc');
require_once('lib/enriched.inc');
require_once('include/rcube_smtp.inc');
@@ -48,7 +47,11 @@
// set message set for search result
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']]))
  {
  $IMAP->set_search_set($_SESSION['search'][$_REQUEST['_search']]);
  $OUTPUT->set_env('search_request', $_REQUEST['_search']);
  $OUTPUT->set_env('search_text', $_SESSION['last_text_search']);
  }
// define url for getting message parts
@@ -72,7 +75,7 @@
// set page title
if (empty($_action) || $_action == 'list')
  $OUTPUT->set_pagetitle(rcube_charset_convert($IMAP->get_mailbox_name(), 'UTF-7'));
  $OUTPUT->set_pagetitle(rcmail_localize_foldername($IMAP->get_mailbox_name()));
@@ -286,6 +289,7 @@
    $OUTPUT->set_env('attachmenticon', $skin_path . $attrib['attachmenticon']);
  
  $OUTPUT->set_env('messages', $a_js_message_arr);
  $OUTPUT->set_env('coltypes', $a_show_cols);
  
  $OUTPUT->include_script('list.js');
  
@@ -403,30 +407,43 @@
  if (!$attrib['id'])
    $attrib['id'] = 'rcmquotadisplay';
  if(isset($attrib['display']))
    $_SESSION['quota_display'] = $attrib['display'];
  $OUTPUT->add_gui_object('quotadisplay', $attrib['id']);
  // allow the following attributes to be added to the <span> tag
  $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
  $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'display'));
  $out = '<span' . $attrib_str . '>';
  $out .= rcmail_quota_content($attrib['display']);
  $out .= rcmail_quota_content();
  $out .= '</span>';
  return $out;
  }
function rcmail_quota_content($display)
function rcmail_quota_content($quota=NULL)
  {
  global $IMAP, $COMM_PATH;
  if (!$IMAP->get_capability('QUOTA'))
    $quota_text = rcube_label('unknown');
  else if ($quota = $IMAP->get_quota())
  $display = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
  if (is_array($quota) && !empty($quota['used']) && !empty($quota['total']))
    {
    $quota_text = sprintf("%s / %s (%.0f%%)",
                          show_bytes($quota["used"] * 1024),
                          show_bytes($quota["total"] * 1024),
                          $quota["percent"]);
      if (!isset($quota['percent']))
        $quota['percent'] = $quota['used'] / $quota['total'];
    }
  elseif (!$IMAP->get_capability('QUOTA'))
    return rcube_label('unknown');
  else
    $quota = $IMAP->get_quota();
  if ($quota)
    {
    $quota_text = sprintf('%s / %s (%.0f%%)',
                          show_bytes($quota['used'] * 1024),
                          show_bytes($quota['total'] * 1024),
                          $quota['percent']);
    // show quota as image (by Brett Patterson)
    if ($display == 'image' && function_exists('imagegif'))
@@ -474,6 +491,127 @@
                                              'count' => $max)));
  return Q($out);
  }
/* Stolen from Squirrelmail */
function sq_deent(&$attvalue, $regex, $hex=false)
  {
  $ret_match = false;
  preg_match_all($regex, $attvalue, $matches);
  if (is_array($matches) && sizeof($matches[0]) > 0)
    {
    $repl = Array();
    for ($i = 0; $i < sizeof($matches[0]); $i++)
      {
      $numval = $matches[1][$i];
      if ($hex)
        $numval = hexdec($numval);
      $repl{$matches[0][$i]} = chr($numval);
      }
    $attvalue = strtr($attvalue, $repl);
    return true;
    }
  else
    return false;
  }
/* Stolen verbatim from Squirrelmail */
function sq_defang(&$attvalue)
  {
  /* Skip this if there aren't ampersands or backslashes. */
  if ((strpos($attvalue, '&') === false) &&
      (strpos($attvalue, '\\') === false))
    return;
  $m = false;
  do
    {
    $m = false;
    $m = $m || sq_deent($attvalue, '/\&#0*(\d+);*/s');
    $m = $m || sq_deent($attvalue, '/\&#x0*((\d|[a-f])+);*/si', true);
    $m = $m || sq_deent($attvalue, '/\\\\(\d+)/s', true);
    } while ($m == true);
  $attvalue = stripslashes($attvalue);
  }
function rcmail_html_filter($html)
  {
  preg_match_all('/<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|\'.*?\'|[^\'">\s]+))?)+\s*|\s*)\/?>/', $html, $tags);
  /* From Squirrelmail: Translate all dangerous Unicode or Shift_JIS characters which are accepted by
   * IE as regular characters. */
  $replace = array(array('&#x029F;', '&#0671;',  /* L UNICODE IPA Extension */
                         '&#x0280;', '&#0640;',  /* R UNICODE IPA Extension */
                         '&#x0274;', '&#0628;',  /* N UNICODE IPA Extension */
                         '&#xFF25;', '&#65317;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER E */
                         '&#xFF45;', '&#65349;', /* Unicode FULLWIDTH LATIN SMALL LETTER E */
                         '&#xFF38;', '&#65336;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER X */
                         '&#xFF58;', '&#65368;', /* Unicode FULLWIDTH LATIN SMALL LETTER X */
                         '&#xFF30;', '&#65328;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER P */
                         '&#xFF50;', '&#65360;', /* Unicode FULLWIDTH LATIN SMALL LETTER P */
                         '&#xFF32;', '&#65330;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER R */
                         '&#xFF52;', '&#65362;', /* Unicode FULLWIDTH LATIN SMALL LETTER R */
                         '&#xFF33;', '&#65331;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER S */
                         '&#xFF53;', '&#65363;', /* Unicode FULLWIDTH LATIN SMALL LETTER S */
                         '&#xFF29;', '&#65321;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER I */
                         '&#xFF49;', '&#65353;', /* Unicode FULLWIDTH LATIN SMALL LETTER I */
                         '&#xFF2F;', '&#65327;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER O */
                         '&#xFF4F;', '&#65359;', /* Unicode FULLWIDTH LATIN SMALL LETTER O */
                         '&#xFF2E;', '&#65326;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER N */
                         '&#xFF4E;', '&#65358;', /* Unicode FULLWIDTH LATIN SMALL LETTER N */
                         '&#xFF2C;', '&#65324;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER L */
                         '&#xFF4C;', '&#65356;', /* Unicode FULLWIDTH LATIN SMALL LETTER L */
                         '&#xFF35;', '&#65333;', /* Unicode FULLWIDTH LATIN CAPITAL LETTER U */
                         '&#xFF55;', '&#65365;', /* Unicode FULLWIDTH LATIN SMALL LETTER U */
                         '&#x207F;', '&#8319;' , /* Unicode SUPERSCRIPT LATIN SMALL LETTER N */
                         "\xEF\xBC\xA5", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER E */
                                         /* in unicode this is some Chinese char range */
                         "\xEF\xBD\x85", /* Shift JIS FULLWIDTH LATIN SMALL LETTER E */
                         "\xEF\xBC\xB8", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER X */
                         "\xEF\xBD\x98", /* Shift JIS FULLWIDTH LATIN SMALL LETTER X */
                         "\xEF\xBC\xB0", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER P */
                         "\xEF\xBD\x90", /* Shift JIS FULLWIDTH LATIN SMALL LETTER P */
                         "\xEF\xBC\xB2", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER R */
                         "\xEF\xBD\x92", /* Shift JIS FULLWIDTH LATIN SMALL LETTER R */
                         "\xEF\xBC\xB3", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER S */
                         "\xEF\xBD\x93", /* Shift JIS FULLWIDTH LATIN SMALL LETTER S */
                         "\xEF\xBC\xA9", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER I */
                         "\xEF\xBD\x89", /* Shift JIS FULLWIDTH LATIN SMALL LETTER I */
                         "\xEF\xBC\xAF", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER O */
                         "\xEF\xBD\x8F", /* Shift JIS FULLWIDTH LATIN SMALL LETTER O */
                         "\xEF\xBC\xAE", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER N */
                         "\xEF\xBD\x8E", /* Shift JIS FULLWIDTH LATIN SMALL LETTER N */
                         "\xEF\xBC\xAC", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER L */
                         "\xEF\xBD\x8C", /* Shift JIS FULLWIDTH LATIN SMALL LETTER L */
                         "\xEF\xBC\xB5", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER U */
                         "\xEF\xBD\x95", /* Shift JIS FULLWIDTH LATIN SMALL LETTER U */
                         "\xE2\x81\xBF", /* Shift JIS FULLWIDTH SUPERSCRIPT N */
                         "\xCA\x9F",   /* L UNICODE IPA Extension */
                         "\xCA\x80",   /* R UNICODE IPA Extension */
                         "\xC9\xB4"),  /* N UNICODE IPA Extension */
                   array('l', 'l', 'r', 'r', 'n', 'n', 'E', 'E', 'e', 'e', 'X', 'X', 'x', 'x',
                         'P', 'P', 'p', 'p', 'R', 'R', 'r', 'r', 'S', 'S', 's', 's', 'I', 'I',
                         'i', 'i', 'O', 'O', 'o', 'o', 'N', 'N', 'n', 'n', 'L', 'L', 'l', 'l',
                         'U', 'U', 'u', 'u', 'n', 'n', 'E', 'e', 'X', 'x', 'P', 'p', 'R', 'r',
                         'S', 's', 'I', 'i', 'O', 'o', 'N', 'n', 'L', 'l', 'U', 'u', 'n', 'l', 'r', 'n'));
  if ((count($tags)>3) && (count($tags[3])>0))
    foreach ($tags[3] as $nr=>$value)
      {
      /* Remove comments */
      $newvalue = preg_replace('/(\/\*.*\*\/)/','$2',$value);
      /* Translate dangerous characters */
      $newvalue = str_replace($replace[0], $replace[1], $newvalue);
      sq_defang($newvalue);
      /* Rename dangerous CSS */
      $newvalue = preg_replace('/expression/i', 'idiocy', $newvalue);
      $newvalue = preg_replace('/url/i', 'idiocy', $newvalue);
      $newattrs = preg_replace('/'.preg_quote($value, '/').'$/', $newvalue, $tags[1][$nr]);
      $newtag = preg_replace('/'.preg_quote($tags[1][$nr], '/').'/', $newattrs, $tags[0][$nr]);
      $html = preg_replace('/'.preg_quote($tags[0][$nr], '/').'/', $newtag, $html);
      }
  return $html;
  }
@@ -528,7 +666,7 @@
      $body = preg_replace($remote_patterns, $remote_replaces, $body);
      }
    return Q($body, 'show', FALSE);
    return Q(rcmail_html_filter($body), 'show', FALSE);
    }
  // text/enriched
@@ -553,8 +691,8 @@
    $convert_patterns[] = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/ie';
    $convert_replaces[] = "rcmail_str_replacement('<a href=\"mailto:\\1\" onclick=\"return ".JS_OBJECT_NAME.".command(\'compose\',\'\\1\',this)\">\\1</a>', \$replace_strings)";
    
    if ($part->ctype_parameters['format'] != 'flowed')
      $body = wordwrap(trim($body), 80);
//    if ($part->ctype_parameters['format'] != 'flowed')
//      $body = wordwrap(trim($body), 80);
    $body = preg_replace($convert_patterns, $convert_replaces, $body);
@@ -569,10 +707,10 @@
      $quotation = '';
      $q = 0;
      
      if (preg_match('/^(>+\s*)/', $line, $regs))
      if (preg_match('/^(>+\s*)+/', $line, $regs))
        {
        $q = strlen(preg_replace('/\s/', '', $regs[1]));
        $line = substr($line, strlen($regs[1]));
        $q    = strlen(preg_replace('/\s/', '', $regs[0]));
        $line = substr($line, strlen($regs[0]));
        if ($q > $quote_level)
          $quotation = str_repeat('<blockquote>', $q - $quote_level);
@@ -634,7 +772,7 @@
    $structure->type = 'content';
    $a_return_parts[] = &$structure;
    }
  // message contains alternative parts
  else if ($message_ctype_primary=='multipart' && $message_ctype_secondary=='alternative' && is_array($structure->parts))
    {
@@ -740,6 +878,10 @@
        $a_return_parts = array_merge($a_return_parts, $parts);
        $a_attachments = array_merge($a_attachments, $attachmnts);
        }
      // ignore "virtual" protocol parts
      else if ($primary_type=='protocol')
        continue;
      // part is file/attachment
      else if ($mail_part->disposition=='attachment' || $mail_part->disposition=='inline' || $mail_part->headers['content-id'] ||
@@ -857,7 +999,7 @@
  if (!$attrib['id'])
    $attrib['id'] = 'rcmailMsgBody';
  $safe_mode = intval($_GET['_safe']);
  $safe_mode = $MESSAGE['is_safe'] || intval($_GET['_safe']);
  $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
  $out = '<div '. $attrib_str . ">\n";
  
@@ -980,7 +1122,7 @@
  while ($body != $prev_body)
    {
    $prev_body = $body;
    $body = preg_replace('/(<[^!][^>]*\s)(on[^=>]+)=([^>]+>)/im', '$1__removed=$3', $body);
    $body = preg_replace('/(<[^!][^>]*\s)on(?:load|unload|click|dblclick|mousedown|mouseup|mouseover|mousemove|mouseout|focus|blur|keypress|keydown|keyup|submit|reset|select|change)=([^>]+>)/im', '$1__removed=$2', $body);
    $body = preg_replace('/(<[^!][^>]*\shref=["\']?)(javascript:)([^>]*?>)/im', '$1null:$3', $body);
    }
@@ -997,7 +1139,8 @@
  // add comments arround html and other tags
  $out = preg_replace(array(
      '/(<!DOCTYPE.+)/i',
      '/(<!DOCTYPE[^>]*>)/i',
      '/(<\?xml[^>]*>)/i',
      '/(<\/?html[^>]*>)/i',
      '/(<\/?head[^>]*>)/i',
      '/(<title[^>]*>.*<\/title>)/Ui',
@@ -1196,12 +1339,11 @@
  if (!is_array($MESSAGE) || !is_array($MESSAGE['parts']) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE['parts'][$part])
    return '';
    
  $part = &$MESSAGE['parts'][$part];
  $part = $MESSAGE['parts'][$part];
  $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'cellspacing', 'cellpadding', 'border', 'summary'));
  $out = '<table '. $attrib_str . ">\n";
  
  if ($filename)
  if ($part->filename)
    {
    $out .= sprintf('<tr><td class="title">%s</td><td>%s</td><td>[<a href="./?%s">%s</a>]</tr>'."\n",
                    Q(rcube_label('filename')),
@@ -1306,11 +1448,85 @@
      $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from");
    }
  
  if ($sent)  // remove MDN headers after sending
    unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']);
  
  $message->_headers = array();
  $message->headers($headers);
  
  return $sent;
}
function rcmail_send_mdn($uid)
{
  global $CONFIG, $USER, $IMAP;
  $message = array('UID' => $uid);
  $message['headers'] = $IMAP->get_headers($message['UID']);
  $message['subject'] = rcube_imap::decode_mime_string($message['headers']->subject, $message['headers']->charset);
  if ($message['headers']->mdn_to && !$message['headers']->mdn_sent)
  {
    $identity = $USER->get_identity();
    $sender = format_email_recipient($identity['email'], $identity['name']);
    $recipient = array_shift($IMAP->decode_address_list($message['headers']->mdn_to));
    $mailto = $recipient['mailto'];
    $compose = new rc_mail_mime(rcmail_header_delm());
    $compose->setParam(array(
      'text_encoding' => 'quoted-printable',
      'html_encoding' => 'quoted-printable',
      'head_encoding' => 'quoted-printable',
      'head_charset'  => RCMAIL_CHARSET,
      'html_charset'  => RCMAIL_CHARSET,
      'text_charset'  => RCMAIL_CHARSET,
    ));
    // compose headers array
    $headers = array(
      'Date' => date('r'),
      'From' => $sender,
      'To'   => $message['headers']->mdn_to,
      'Subject' => rcube_label('receiptread') . ': ' . $message['subject'],
      'Message-ID' => sprintf('<%s@%s>', md5(uniqid('rcmail'.rand(),true)), rcmail_mail_domain($_SESSION['imap_host'])),
      'X-Sender' => $identity['email'],
      'Content-Type' => 'multipart/report; report-type=disposition-notification',
    );
    if (!empty($CONFIG['useragent']))
      $headers['User-Agent'] = $CONFIG['useragent'];
    $body = rcube_label("yourmessage") . "\r\n\r\n" .
      "\t" . rcube_label("to") . ': ' . rcube_imap::decode_mime_string($message['headers']->to, $message['headers']->charset) . "\r\n" .
      "\t" . rcube_label("subject") . ': ' . $message['subject'] . "\r\n" .
      "\t" . rcube_label("sent") . ': ' . format_date(strtotime($message['headers']->date), $CONFIG['date_long']) . "\r\n" .
      "\r\n" . rcube_label("receiptnote") . "\r\n";
    $ua = !empty($CONFIG['useragent']) ? $CONFIG['useragent'] : "RoundCube Webmail (Version ".RCMAIL_VERSION.")";
    $report = "Reporting-UA: $ua\r\n";
    if ($message['headers']->to)
        $report .= "Original-Recipient: {$message['headers']->to}\r\n";
    $report .= "Final-Recipient: rfc822; {$identity['email']}\r\n" .
               "Original-Message-ID: {$message['headers']->messageID}\r\n" .
               "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
    $compose->headers($headers, true);
    $compose->setTXTBody($body);
    $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline');
    $sent = rcmail_deliver_message($compose, $identity['email'], $mailto);
    if ($sent)
    {
      $IMAP->set_flag($message['UID'], 'MDNSENT');
      return true;
    }
  }
  return false;
}
@@ -1325,7 +1541,7 @@
  'messagecontentframe' => 'rcmail_messagecontent_frame',
  'messagepartframe' => 'rcmail_message_part_frame',
  'messagepartcontrols' => 'rcmail_message_part_controls',
  'searchform' => 'rcmail_search_form'
  'searchform' => array($OUTPUT, 'search_form'),
));
?>