alecpl
2010-05-18 677e1f26fe47cc0c3e0819cb99a9024af49a619c
program/steps/mail/compose.inc
@@ -44,6 +44,8 @@
  
  // process values like "mailto:foo@bar.com?subject=new+message&cc=another"
  if ($_SESSION['compose']['param']['to']) {
    // #1486037: remove "mailto:" prefix
    $_SESSION['compose']['param']['to'] = preg_replace('/^mailto:/i', '', $_SESSION['compose']['param']['to']);
    $mailto = explode('?', $_SESSION['compose']['param']['to']);
    if (count($mailto) > 1) {
      $_SESSION['compose']['param']['to'] = $mailto[0];
@@ -53,9 +55,12 @@
    }
  }
  
  // select folder where to save the sent message
  $_SESSION['compose']['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox');
  // pipe compose parameters thru plugins
  $plugin = $RCMAIL->plugins->exec_hook('message_compose', $_SESSION['compose']);
  $_SESSION['compose']['param'] = array_merge($_SESSION['compose']['param'], $plugin['param']);
  $_SESSION['compose']['param'] = array_merge($_SESSION['compose']['param'], $plugin['param']);
  // add attachments listed by message_compose hook
  if (is_array($plugin['attachments'])) {
@@ -128,13 +133,20 @@
else
  $OUTPUT->set_env('show_sig', false);
// set line length for body wrapping
$LINE_LENGTH = $RCMAIL->config->get('line_length', 75);
if (!empty($msg_uid))
{
  // similar as in program/steps/mail/show.inc
  // re-set 'prefer_html' to have possibility to use html part for compose
  $CONFIG['prefer_html'] = $CONFIG['htmleditor'] || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT;
  $CONFIG['prefer_html'] = $CONFIG['prefer_html'] || $CONFIG['htmleditor'] || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT;
  $MESSAGE = new rcube_message($msg_uid);
  
  // make sure message is marked as read
  if ($MESSAGE && $MESSAGE->headers && !$MESSAGE->headers->seen)
    $IMAP->set_flag($msg_uid, 'SEEN');
  if (!empty($MESSAGE->headers->charset))
    $IMAP->set_charset($MESSAGE->headers->charset);
    
@@ -146,21 +158,33 @@
    if (!empty($_SESSION['compose']['param']['all']))
      $MESSAGE->reply_all = 1;
    $OUTPUT->set_env('compose_mode', 'reply');
  }
  else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
  {
    if($MESSAGE->headers->in_reply_to)
    if ($MESSAGE->headers->others['x-draft-info'])
    {
      // TODO: how to get reply_uid/forward_uid value, maybe we must set X-Reply-UID/X-Forward-UID
      // $_SESSION['compose']['reply_uid'] = ?
      // $_SESSION['compose']['forward_uid'] = ?
      $_SESSION['compose']['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
      // get reply_uid/forward_uid to flag the original message when sending
      $info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']);
      if ($info['type'] == 'reply')
        $_SESSION['compose']['reply_uid'] = $info['uid'];
      else if ($info['type'] == 'forward')
        $_SESSION['compose']['forward_uid'] = $info['uid'];
      $_SESSION['compose']['mailbox'] = $info['folder'];
    }
    if ($MESSAGE->headers->in_reply_to)
      $_SESSION['compose']['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
    $_SESSION['compose']['references']  = $MESSAGE->headers->references;
  }
  else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
  {
    $_SESSION['compose']['forward_uid'] = $msg_uid;
    $OUTPUT->set_env('compose_mode', 'forward');
  }
}
@@ -360,7 +384,7 @@
      if ($compose_mode == RCUBE_COMPOSE_REPLY && is_array($MESSAGE->compose_from))
        $MESSAGE->compose_from[] = $sql_arr['email'];
      if (empty($_POST['_from']))
      if (empty($_POST['_from']) && empty($_SESSION['compose']['param']['from']))
      {
        // set draft's identity
        if ($compose_mode == RCUBE_COMPOSE_DRAFT && strstr($MESSAGE->headers->from, $sql_arr['email']))
@@ -374,6 +398,8 @@
    // overwrite identity selection with post parameter
    if (!empty($_POST['_from']))
      $from_id = get_input_value('_from', RCUBE_INPUT_POST);
    else if (!empty($_SESSION['compose']['param']['from']))
      $from_id = $_SESSION['compose']['param']['from'];
    $out = $select_from->show($from_id);
@@ -395,7 +421,7 @@
function rcmail_compose_body($attrib)
{
  global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode;
  global $RCMAIL, $CONFIG, $OUTPUT, $MESSAGE, $compose_mode, $LINE_LENGTH;
  
  list($form_start, $form_end) = get_form_tags($attrib);
  unset($attrib['form']);
@@ -424,10 +450,20 @@
  }
  else if ($compose_mode)
  {
    if (($isHtml || $compose_mode == RCUBE_COMPOSE_DRAFT) && $MESSAGE->has_html_part())
    $has_html_part = $MESSAGE->has_html_part();
    if (($isHtml || $compose_mode == RCUBE_COMPOSE_DRAFT) && $has_html_part)
    {
      $body = $MESSAGE->first_html_part();
      $isHtml = true;
    }
    else if ($has_html_part)
    {
      // use html part if it has been used for message (pre)viewing
      // decrease line length for quoting
      $len = $compose_mode == RCUBE_COMPOSE_REPLY ? $LINE_LENGTH-2 : $LINE_LENGTH;
      $txt = new html2text($MESSAGE->first_html_part(), false, true, $len);
      $body = $txt->get_text();
      $isHtml = false;
    }
    else
    {
@@ -448,8 +484,19 @@
  $plugin = $RCMAIL->plugins->exec_hook('message_compose_body',
    array('body' => $body, 'html' => $isHtml, 'mode' => $compose_mode));
  $body = $plugin['body'];
  $body = $plugin['body'];
  unset($plugin);
  // add blocked.gif attachment (#1486516)
  if ($isHtml && preg_match('#<img src="\./program/blocked\.gif"#', $body)) {
    if ($attachment = rcmail_save_image('program/blocked.gif', 'image/gif')) {
      $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
      $body = preg_replace('#\./program/blocked\.gif#',
        $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'],
        $body);
    }
  }
  $out = $form_start ? "$form_start\n" : '';
  $saveid = new html_hiddenfield(array('name' => '_draft_saveid', 'value' => $compose_mode==RCUBE_COMPOSE_DRAFT ? str_replace(array('<','>'), "", $MESSAGE->headers->messageID) : ''));
@@ -475,20 +522,40 @@
  // include GoogieSpell
  if (!empty($CONFIG['enable_spellcheck'])) {
    $lang = strtolower(substr($_SESSION['language'], 0, 2));
    $spellcheck_langs = (array)$RCMAIL->config->get('spellcheck_languages', array('da'=>'Dansk', 'de'=>'Deutsch', 'en' => 'English', 'es'=>'Español', 'fr'=>'Français', 'it'=>'Italiano', 'nl'=>'Nederlands', 'pl'=>'Polski', 'pt'=>'Português', 'fi'=>'Suomi', 'sv'=>'Svenska'));
    $engine = $RCMAIL->config->get('spellcheck_engine','googie');
    $spellcheck_langs = (array) $RCMAIL->config->get('spellcheck_languages',
      array('da'=>'Dansk', 'de'=>'Deutsch', 'en' => 'English', 'es'=>'Español',
            'fr'=>'Français', 'it'=>'Italiano', 'nl'=>'Nederlands', 'pl'=>'Polski',
            'pt'=>'Português', 'fi'=>'Suomi', 'sv'=>'Svenska'));
    // googie works only with two-letter codes
    if ($engine == 'googie') {
      $lang = strtolower(substr($_SESSION['language'], 0, 2));
      $spellcheck_langs_googie = array();
      foreach ($spellcheck_langs as $key => $name)
        $spellcheck_langs_googie[strtolower(substr($key,0,2))] = $name;
        $spellcheck_langs = $spellcheck_langs_googie;
    }
    else {
      $lang = $_SESSION['language'];
      // if not found in the list, try with two-letter code
      if (!$spellcheck_langs[$lang])
        $lang = strtolower(substr($lang, 0, 2));
    }
    if (!$spellcheck_langs[$lang])
      $lang = 'en';
    $editor_lang_set = array();
    foreach ($spellcheck_langs as $key => $name) {
      $editor_lang_set[] = ($key == $lang ? '+' : '') . JQ($name).'='.JQ($key);
      }
    }
    
    $OUTPUT->include_script('googiespell.js');
    $OUTPUT->add_script(sprintf(
      "var googie = new GoogieSpell('\$__skin_path/images/googiespell/','%s&_action=spell&lang=');\n".
      "var googie = new GoogieSpell('\$__skin_path/images/googiespell/','?_task=utils&_action=spell&lang=');\n".
      "googie.lang_chck_spell = \"%s\";\n".
      "googie.lang_rsm_edt = \"%s\";\n".
      "googie.lang_close = \"%s\";\n".
@@ -499,7 +566,6 @@
      "googie.setSpellContainer('spellcheck-control');\n".
      "googie.decorateTextarea('%s');\n".
      "%s.set_env('spellcheck', googie);",
      $RCMAIL->comm_path,
      JQ(Q(rcube_label('checkspelling'))),
      JQ(Q(rcube_label('resumeediting'))),
      JQ(Q(rcube_label('close'))),
@@ -522,7 +588,7 @@
function rcmail_create_reply_body($body, $bodyIsHtml)
{
  global $RCMAIL, $MESSAGE;
  global $RCMAIL, $MESSAGE, $LINE_LENGTH;
  if (!$bodyIsHtml) {
    // try to remove the signature
@@ -532,7 +598,7 @@
    }
    // soft-wrap message first
    $body = rcmail_wrap_quoted($body, 75);
    $body = rcmail_wrap_quoted($body, $LINE_LENGTH);
    $body = rtrim($body, "\r\n");
@@ -554,7 +620,7 @@
    // add title line(s)
    $prefix = rc_wordwrap(sprintf("On %s, %s wrote:\n",
      $MESSAGE->headers->date,
      $MESSAGE->get_header('from')), 76);
      $MESSAGE->get_header('from')), $LINE_LENGTH);
    $suffix = '';
    
@@ -570,17 +636,17 @@
    $body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map);
    // build reply (quote content)
    $prefix = sprintf("On %s, %s wrote:<br />\n",
    $prefix = sprintf("<p>On %s, %s wrote:</p>\n",
      $MESSAGE->headers->date,
      htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $RCMAIL->output->get_charset()));
    $prefix .= '<blockquote type="cite" style="padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px; width:100%">';
    $prefix .= '<blockquote>';
    if ($RCMAIL->config->get('top_posting')) {
      $prefix = "<p></p>" . $prefix;
      $suffix = "</blockquote>";
      $prefix = '<br>' . $prefix;
      $suffix = '</blockquote>';
    }
    else {
      $suffix = "</blockquote><p></p>";
      $suffix = '</blockquote><p></p>';
    }
  }
@@ -603,8 +669,12 @@
    $prefix .= 'Date: ' . $MESSAGE->headers->date . "\n";
    $prefix .= 'From: ' . $MESSAGE->get_header('from') . "\n";
    $prefix .= 'To: ' . $MESSAGE->get_header('to') . "\n";
    if ($MESSAGE->headers->cc)
      $prefix .= 'Cc: ' . $MESSAGE->get_header('cc') . "\n";
    if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
      $prefix .= 'Reply-To: ' . $MESSAGE->get_header('replyto') . "\n";
    $prefix .= "\n";
  }
  else
@@ -615,7 +685,7 @@
    $body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map);
    $prefix = sprintf(
      "<p></p><p>-------- Original Message --------</p>" .
      "<br /><p>-------- Original Message --------</p>" .
        "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" .
        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Subject: </th><td>%s</td></tr>" .
        "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Date: </th><td>%s</td></tr>" .
@@ -625,6 +695,10 @@
      Q($MESSAGE->headers->date),
      htmlspecialchars(Q($MESSAGE->get_header('from'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()),
      htmlspecialchars(Q($MESSAGE->get_header('to'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()));
    if ($MESSAGE->headers->cc)
      $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Cc: </th><td>%s</td></tr>",
        htmlspecialchars(Q($MESSAGE->get_header('cc'), 'replace'), ENT_COMPAT, $OUTPUT->get_charset()));
    if ($MESSAGE->headers->replyto && $MESSAGE->headers->replyto != $MESSAGE->headers->from)
      $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">Reply-To: </th><td>%s</td></tr>",
@@ -728,9 +802,10 @@
    'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
    'content_id' => $part->content_id,
    'data' => $data,
    'path' => $path
    'path' => $path,
    'size' => $path ? filesize($path) : strlen($data),
  );
  $attachment = rcmail::get_instance()->plugins->exec_hook('save_attachment', $attachment);
  if ($attachment['status']) {
@@ -743,6 +818,37 @@
  return false;
}
function rcmail_save_image($path, $mimetype='')
{
  // handle attachments in memory
  $data = file_get_contents($path);
  $attachment = array(
    'name' => rcmail_basename($path),
    'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name),
    'data' => $data,
    'size' => strlen($data),
  );
  $attachment = rcmail::get_instance()->plugins->exec_hook('save_attachment', $attachment);
  if ($attachment['status']) {
    unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
    return $attachment;
  }
  return false;
}
function rcmail_basename($filename)
{
  // basename() is not unicode safe and locale dependent
  if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
    return preg_replace('/^.*[\\\\\\/]/', '', $filename);
  } else {
    return preg_replace('/^.*[\/]/', '', $filename);
  }
}
function rcmail_compose_subject($attrib)
{
@@ -865,7 +971,7 @@
      html::div(null, rcmail_compose_attachment_field(array('size' => $attrib[attachmentfieldsize]))) .
      html::div('hint', rcube_label(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) .
      html::div('buttons',
        $button->show(rcube_label('close'), array('class' => 'button', 'onclick' => "document.getElementById('$attrib[id]').style.visibility='hidden'")) . ' ' .
        $button->show(rcube_label('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' .
        $button->show(rcube_label('upload'), array('class' => 'button mainaction', 'onclick' => JS_OBJECT_NAME . ".command('send-attachment', this.form)"))
      )
    )
@@ -957,7 +1063,7 @@
  if (empty($attrib['name']))
    $attrib['name'] = 'editorSelect';
    
  $attrib['onchange'] = "return rcmail_toggle_editor(this.value=='html', '".$attrib['editorid']."', '_is_html')";
  $attrib['onchange'] = "return rcmail_toggle_editor(this, '".$attrib['editorid']."', '_is_html')";
  $select = new html_select($attrib);
@@ -981,7 +1087,7 @@
{
  $attrib['name'] = '_store_target';
  $select = rcmail_mailbox_select(array_merge($attrib, array('noselection' => '- '.rcube_label('dontsave').' -')));
  return $select->show(rcmail::get_instance()->config->get('sent_mbox'), $attrib);
  return $select->show($_SESSION['compose']['param']['sent_mbox'], $attrib);
}