[ Index ]
 

Code source de IMP H3 (4.1.5)

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/ -> compose.php (source)

   1  <?php
   2  /**
   3   * $Horde: imp/compose.php,v 2.800.2.79 2007/04/10 19:40:27 jan Exp $
   4   *
   5   * Copyright 1999-2007 Charles J. Hagenbuch <chuck@horde.org>
   6   * Copyright 1999-2007 Jon Parise <jon@horde.org>
   7   * Copyright 2002-2007 Michael Slusarz <slusarz@bigworm.colorado.edu>
   8   *
   9   * See the enclosed file COPYING for license information (GPL).  If you
  10   * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
  11   */
  12  
  13  /**
  14   * Determines the actionID.
  15   */
  16  function _getActionID()
  17  {
  18      if (!($aid = Util::getFormData('actionID'))) {
  19          foreach (array('send_message', 'save_draft', 'cancel_compose', 'add_attachment') as $val) {
  20              if (Util::getFormData('btn_' . $val)) {
  21                  $aid = $val;
  22                  break;
  23              }
  24          }
  25      }
  26  
  27      /* Alter the 'Send Message' action if the "Spell check before sending
  28       * message?" preference has been enabled. */
  29      if (($aid == 'send_message') &&
  30          (Util::getFormData('done_action') != 'send') &&
  31          !empty($GLOBALS['conf']['utils']['spellchecker']) &&
  32          $GLOBALS['prefs']->getValue('compose_spellcheck')) {
  33          return 'spell_check_send';
  34      } else {
  35          return $aid;
  36      }
  37  }
  38  
  39  /**
  40   * Return an url for mailbox.php depending on what kind of start/page
  41   * information we have.
  42   *
  43   * @param boolean $encode  Whether or not to encode entities in the URL.
  44   * @param string $url      The base URL.
  45   */
  46  function _mailboxReturnURL($encode, $url = null)
  47  {
  48      if (empty($url)) {
  49          $url = Horde::applicationUrl('mailbox.php');
  50      }
  51  
  52      foreach (array('start', 'page') as $key) {
  53          if (($param = Util::getFormData($key))) {
  54              $url = Util::addParameter($url, $key, $param, $encode);
  55          }
  56      }
  57  
  58      return $url;
  59  }
  60  
  61  /**
  62   * Returns a To:, Cc: or Bcc: list build from a selection based on 'expand
  63   * names'.
  64   */
  65  function _getAddressList($field, $expand = false)
  66  {
  67      $to = trim(Util::getFormData($field));
  68      if (!empty($to)) {
  69          $to = implode(', ', _cleanAddrList(array($to), false));
  70          return $expand ? $to : _formatAddr($to);
  71      }
  72  
  73      $to_list = Util::getFormData($field . '_list');
  74      $to = Util::getFormData($field . '_field');
  75  
  76      $tmp = array();
  77      if (is_array($to)) {
  78          foreach ($to as $key => $address) {
  79              $tmp[$key] = $address;
  80          }
  81      }
  82      if (is_array($to_list)) {
  83          foreach ($to_list as $key => $address) {
  84              if ($address != '') {
  85                  $tmp[$key] = $address;
  86              }
  87          }
  88      }
  89  
  90      $to_new = trim(Util::getFormData($field . '_new'));
  91      if (!empty($to_new)) {
  92          $tmp[] = $to_new;
  93      }
  94      return implode(', ', $tmp);
  95  }
  96  
  97  /**
  98   * Expand addresses in a header.
  99   */
 100  function _expandAddresses($header)
 101  {
 102      $result = IMP::expandAddresses(_getAddressList($header, true), true);
 103  
 104      if (is_array($result)) {
 105          $GLOBALS['notification']->push(_("Please resolve ambiguous or invalid addresses."), 'horde.warning');
 106      } elseif (is_a($result, 'PEAR_Error')) {
 107          $error = $result;
 108          $result = array();
 109  
 110          $list = $error->getUserInfo();
 111          if (is_array($list)) {
 112              foreach ($list as $entry) {
 113                  if (is_object($entry)) {
 114                      $result[] = $entry->getUserInfo();
 115                  } else {
 116                      $result[] = $entry;
 117                  }
 118              }
 119          }
 120          $GLOBALS['notification']->push($error, 'horde.warning');
 121      }
 122  
 123      return $result;
 124  }
 125  
 126  /**
 127   * Checks for non-standard address formats, such as separating with spaces
 128   * or semicolons, and return a "cleaned address string".
 129   */
 130  function _formatAddr($addr)
 131  {
 132      /* If there are angle brackets (<>), or a colon (group name
 133         delimiter), assume the user knew what they were doing. */
 134      if (!empty($addr) &&
 135          (strpos($addr, '>') === false) &&
 136          (strpos($addr, ':') === false)) {
 137          $addr = trim(strtr($addr, ';,', '  '));
 138          $addr = preg_replace('|\s+|', ', ', $addr);
 139      }
 140  
 141      return $addr;
 142  }
 143  
 144  /**
 145   * Generate a recipient list.
 146   */
 147  function _recipientList($addr)
 148  {
 149      $addrlist = _cleanAddrList($addr, true);
 150  
 151      if (empty($addrlist)) {
 152          return PEAR::raiseError(_("You must enter at least one recipient."));
 153      }
 154  
 155      foreach (MIME::bareAddress(implode(', ', $addrlist), $GLOBALS['imp']['maildomain'], true) as $val) {
 156          if (MIME::is8bit($val)) {
 157              return PEAR::raiseError(sprintf(_("Invalid character in e-mail address: %s."), $val));
 158          }
 159      }
 160  
 161      return $addrlist;
 162  }
 163  
 164  /**
 165   * Returns the charset to use for outgoing messages based on (by replying
 166   * to or forwarding) the given MIME message and the user's default settings
 167   * and any previously selected charset.
 168   */
 169  function _getEncoding($mime_message = null)
 170  {
 171      if ($GLOBALS['charset']) {
 172          return $GLOBALS['charset'];
 173      }
 174  
 175      $encoding = NLS::getEmailCharset();
 176  
 177      if (isset($mime_message)) {
 178          $mime_message = &Util::cloneObject($mime_message);
 179          $mime_part = $mime_message->getBasePart();
 180          if ($mime_part->getPrimaryType() == MIME::type(TYPEMULTIPART)) {
 181              foreach ($mime_part->getParts() as $part) {
 182                  if ($part->getPrimaryType() == MIME::type(TYPETEXT)) {
 183                      $mime_part = $part;
 184                      break;
 185                  }
 186              }
 187          }
 188          if (NLS::getCharset() == 'UTF-8') {
 189              $charset_upper = String::upper($mime_part->getCharset());
 190              if (($charset_upper != 'US-ASCII') &&
 191                  ($charset_upper != String::upper($encoding))) {
 192                  $encoding = 'UTF-8';
 193              }
 194          }
 195      }
 196  
 197      return $encoding;
 198  }
 199  
 200  /**
 201   * Setup the base message MIME_Part object.
 202   */
 203  function _baseMessage(&$imp_compose, $charset, $final_msg = true)
 204  {
 205      $message = String::convertCharset(Util::getFormData('message', ''), NLS::getCharset(), $charset);
 206  
 207      if ($GLOBALS['rtemode']) {
 208          $message_html = $message;
 209          require_once 'Horde/Text/Filter.php';
 210          $message = Text_Filter::filter($message, 'html2text', array('wrap' => false));
 211      }
 212  
 213      /* Get trailer message (if any). */
 214      $trailer = null;
 215      if ($final_msg &&
 216          $GLOBALS['conf']['msg']['append_trailer'] &&
 217          @is_readable(IMP_BASE . '/config/trailer.txt')) {
 218          require_once 'Horde/Text/Filter.php';
 219          $trailer = Text_Filter::filter("\n" . file_get_contents(IMP_BASE . '/config/trailer.txt'), 'environment');
 220          /* If there is a user defined function, call it with the current
 221             trailer as an argument. */
 222          if (!empty($GLOBALS['conf']['hooks']['trailer'])) {
 223              require_once HORDE_BASE . '/config/hooks.php';
 224              if (function_exists('_imp_hook_trailer')) {
 225                  $trailer = call_user_func('_imp_hook_trailer', $trailer);
 226              }
 227          }
 228      }
 229  
 230      /* Set up the body part now. */
 231      $textBody = &new MIME_Part('text/plain');
 232      $textBody->setContents($textBody->replaceEOL($message));
 233      $textBody->setCharset($charset);
 234      if (!is_null($trailer)) {
 235          $textBody->appendContents($trailer);
 236      }
 237  
 238      /* Send in flowed format. */
 239      require_once 'Text/Flowed.php';
 240      $flowed = &new Text_Flowed($textBody->getContents(), $charset);
 241      if (method_exists($flowed, 'setDelSp')) {
 242          $flowed->setDelSp(true);
 243          $textBody->setContentTypeParameter('DelSp', 'Yes');
 244      }
 245      $textBody->setContents($flowed->toFlowed());
 246      $textBody->setContentTypeParameter('format', 'flowed');
 247  
 248      /* Determine whether or not to send a multipart/alternative
 249       * message with an HTML part. */
 250      if (!empty($message_html)) {
 251          $htmlBody = &new MIME_Part('text/html', String::wrap($message_html), null, 'inline');
 252          if (!is_null($trailer)) {
 253              require_once 'Horde/Text/Filter.php';
 254              $htmlBody->appendContents(Text_Filter::filter($trailer, 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null)));
 255          }
 256          $basepart = &new MIME_Part('multipart/alternative');
 257          $textBody->setDescription(_("Plaintext Version of Message"));
 258          $basepart->addPart($textBody);
 259          $htmlBody->setDescription(_("HTML Version of Message"));
 260          $htmlBody->setCharset($charset);
 261  
 262          if ($final_msg) {
 263              /* Any image links will be downloaded and appended to the
 264               * message body. */
 265              $htmlBody = $imp_compose->convertToMultipartRelated($htmlBody);
 266          }
 267          $basepart->addPart($htmlBody);
 268      } else {
 269          $basepart = $textBody;
 270      }
 271  
 272      /* Add attachments now. */
 273      if ($imp_compose->numberOfAttachments()) {
 274          if ((Util::getFormData('link_attachments') && $GLOBALS['conf']['compose']['link_attachments']) ||
 275              !empty($GLOBALS['conf']['compose']['link_all_attachments'])) {
 276              $body = $imp_compose->linkAttachments(Horde::applicationUrl('attachment.php', true), $basepart, Auth::getAuth());
 277          } else {
 278              $body = &new MIME_Part('multipart/mixed');
 279              $body->addPart($basepart);
 280              $imp_compose->buildAllAttachments($body, $charset);
 281          }
 282      } else {
 283          $body = $basepart;
 284      }
 285  
 286      return $body;
 287  }
 288  
 289  /**
 290   * Create the base MIME_Message for sending.
 291   */
 292  function _createMimeMessage($to, $body)
 293  {
 294      require_once 'Horde/MIME/Message.php';
 295      $mime_message = &new MIME_Message($GLOBALS['imp']['maildomain']);
 296  
 297      /* Set up the base message now. */
 298      if ($GLOBALS['usePGP'] &&
 299          in_array($GLOBALS['encrypt'], array(IMP_PGP_ENCRYPT, IMP_PGP_SIGN, IMP_PGP_SIGNENC))) {
 300          if (empty($GLOBALS['imp_pgp'])) {
 301              require_once  IMP_BASE .'/lib/Crypt/PGP.php';
 302              $GLOBALS['imp_pgp'] = &new IMP_PGP();
 303          }
 304          $imp_pgp = &$GLOBALS['imp_pgp'];
 305  
 306          /* Get the user's passphrase, if we need it. */
 307          $passphrase = '';
 308          if (in_array($GLOBALS['encrypt'], array(IMP_PGP_SIGN, IMP_PGP_SIGNENC))) {
 309              /* Check to see if we have the user's passphrase yet. */
 310              $passphrase = $imp_pgp->getPassphrase();
 311              if (empty($passphrase)) {
 312                  $GLOBALS['pgp_passphrase_dialog'] = true;
 313                  return PEAR::raiseError(_("PGP Error: Need passphrase for personal private key."));
 314              }
 315          }
 316  
 317          /* Do the encryption/signing requested. */
 318          switch ($GLOBALS['encrypt']) {
 319          case IMP_PGP_SIGN:
 320              $body = $imp_pgp->IMPsignMIMEPart($body);
 321              break;
 322  
 323          case IMP_PGP_ENCRYPT:
 324              $body = $imp_pgp->IMPencryptMIMEPart($body, $to);
 325              break;
 326  
 327          case IMP_PGP_SIGNENC:
 328              $body = $imp_pgp->IMPsignAndEncryptMIMEPart($body, $to);
 329              break;
 330          }
 331  
 332          /* Check for errors. */
 333          if (is_a($body, 'PEAR_Error')) {
 334              return PEAR::raiseError(_("PGP Error: ") . $body->getMessage());
 335          }
 336      } elseif ($GLOBALS['useSMIME'] &&
 337                in_array($GLOBALS['encrypt'], array(IMP_SMIME_ENCRYPT, IMP_SMIME_SIGN, IMP_SMIME_SIGNENC))) {
 338          if (empty($GLOBALS['imp_smime'])) {
 339              require_once  IMP_BASE. '/lib/Crypt/SMIME.php';
 340              $GLOBALS['imp_smime'] = &new IMP_SMIME();
 341          }
 342          $imp_smime = &$GLOBALS['imp_smime'];
 343  
 344          /* Check to see if we have the user's passphrase yet. */
 345          if (in_array($GLOBALS['encrypt'], array(IMP_SMIME_SIGN, IMP_SMIME_SIGNENC))) {
 346              $passphrase = $imp_smime->getPassphrase();
 347              if ($passphrase === false) {
 348                  $GLOBALS['smime_passphrase_dialog'] = true;
 349                  return PEAR::raiseError(_("S/MIME Error: Need passphrase for personal private key."));
 350              }
 351          }
 352  
 353          /* Do the encryption/signing requested. */
 354          switch ($GLOBALS['encrypt']) {
 355          case IMP_SMIME_SIGN:
 356              $body = $imp_smime->IMPsignMIMEPart($body);
 357              break;
 358  
 359          case IMP_SMIME_ENCRYPT:
 360              $body = $imp_smime->IMPencryptMIMEPart($body, $to[0]);
 361              break;
 362  
 363          case IMP_SMIME_SIGNENC:
 364              $body = $imp_smime->IMPsignAndEncryptMIMEPart($body, $to[0]);
 365              break;
 366          }
 367  
 368          /* Check for errors. */
 369          if (is_a($body, 'PEAR_Error')) {
 370              return PEAR::raiseError(_("S/MIME Error: ") . $body->getMessage());
 371          }
 372      }
 373  
 374      /* Add data to MIME_Message object. */
 375      $mime_message->addPart($body);
 376  
 377      /* Append PGP signature if set in the preferences. */
 378      if ($GLOBALS['usePGP'] && Util::getFormData('pgp_attach_pubkey')) {
 379          if (!isset($GLOBALS['imp_pgp'])) {
 380              require_once  IMP_BASE . '/lib/Crypt/PGP.php';
 381              $GLOBALS['imp_pgp'] = &new IMP_PGP();
 382          }
 383          $mime_message->addPart($GLOBALS['imp_pgp']->publicKeyMIMEPart());
 384      }
 385  
 386      return array('to' => implode(', ', $to), 'msg' => &$mime_message);
 387  }
 388  
 389  function _cleanAddrList($addrs, $multiple)
 390  {
 391      $addrlist = array();
 392  
 393      foreach ($addrs as $val) {
 394          $addr_array = MIME::rfc822Explode($val, ',');
 395          $addr_array = array_map('trim', $addr_array);
 396          foreach ($addr_array as $email) {
 397              if (!empty($email)) {
 398                  $uniques = IMP::bareAddress($email, $multiple);
 399                  if (!$multiple) {
 400                      $uniques = array($uniques);
 401                  }
 402                  foreach ($uniques as $unique) {
 403                      if ($unique && $unique != 'UNEXPECTED_DATA_AFTER_ADDRESS@.SYNTAX-ERROR.') {
 404                          $addrlist[$unique] = $multiple ? $unique : $email;
 405                      } else {
 406                          $addrlist[$email] = $email;
 407                      }
 408                  }
 409              }
 410          }
 411      }
 412  
 413      return array_values($addrlist);
 414  }
 415  
 416  function _popupSuccess()
 417  {
 418      global $registry;
 419      require_once 'Horde/Menu.php';
 420      $menu = &new Menu(HORDE_MENU_MASK_NONE);
 421      $menu->add(Horde::applicationUrl('compose.php'), _("Compose another message"), 'compose.png');
 422      $menu->add('', _("Close this window"), 'close.png', $registry->getImageDir('horde'), '', 'window.close();');
 423      require IMP_TEMPLATES . '/common-header.inc';
 424      require IMP_TEMPLATES . '/compose/success.inc';
 425      IMP::status();
 426      require $registry->get('templates', 'horde') . '/common-footer.inc';
 427  }
 428  
 429  @define('IMP_BASE', dirname(__FILE__));
 430  $session_control = 'netscape';
 431  require_once  IMP_BASE . '/lib/base.php';
 432  require_once  IMP_BASE . '/lib/Compose.php';
 433  require_once  IMP_BASE . '/lib/Folder.php';
 434  require_once 'Horde/Identity.php';
 435  require_once 'Horde/MIME.php';
 436  require_once 'Horde/MIME/Part.php';
 437  
 438  /* The list of state information from compose.php that needs to persist across
 439   * across page loads. */
 440  $s_var = array('to', 'cc', 'bcc', 'to_list', 'cc_list', 'bcc_list',
 441                 'to_field', 'cc_field', 'bcc_field', 'to_new', 'cc_new',
 442                 'bcc_new', 'link_attachments', 'rtemode', 'pgp_attach_pubkey',
 443                 'in_reply_to', 'references', 'identity', 'charset',
 444                 'messageCache', 'popup', 'oldrtemode', 'mailto', 'from',
 445                 'encrypt_options', 'x_priority', 'request_read_receipt',
 446                 'subject', 'reply_index', 'reply_type', 'save_sent_mail',
 447                 'save_attachments_select', 'reloaded', 'sent_mail_folder');
 448  
 449  /* The message text. */
 450  $msg = '';
 451  
 452  /* The headers of the message. */
 453  $header = array();
 454  $header['to'] = '';
 455  $header['cc'] = '';
 456  $header['bcc'] = '';
 457  $header['subject'] = '';
 458  $header['inreplyto'] = Util::getFormData('in_reply_to');
 459  $header['references'] = Util::getFormData('references');
 460  
 461  $get_sig = true;
 462  $pgp_passphrase_dialog = false;
 463  $smime_passphrase_dialog = false;
 464  
 465  /* Some global values. */
 466  $imp_pgp = $imp_smime = $usePGP = $useSMIME = null;
 467  
 468  $identity = &Identity::singleton(array('imp', 'imp'));
 469  $sent_mail_folder = $identity->getValue('sent_mail_folder', Util::getFormData('identity'));
 470  $actionID = _getActionID();
 471  $reply_index = Util::getFormData('reply_index');
 472  $thismailbox = Util::getFormData('thismailbox', $imp['mailbox']);
 473  
 474  /* Check for duplicate submits. */
 475  require_once 'Horde/Token.php';
 476  if (isset($conf['token'])) {
 477      /* If there is a configured token system, set it up. */
 478      $tokenSource = &Horde_Token::singleton($conf['token']['driver'], Horde::getDriverConfig('token', $conf['token']['driver']));
 479  } else {
 480      /* Default to the file system if no config. */
 481      $tokenSource = &Horde_Token::singleton('file');
 482  }
 483  if ($token = Util::getFormData('__formToken_compose')) {
 484      $verified = $tokenSource->verify($token);
 485      /* Notify and reset the actionID. */
 486      if (is_a($verified, 'PEAR_Error')) {
 487          $notification->push($verified);
 488          $actionID = null;
 489      } elseif (!$verified) {
 490          $notification->push(_("You have already submitted this page."), 'horde.error');
 491          $actionID = null;
 492      }
 493  }
 494  
 495  if (($index = Util::getFormData('index'))) {
 496      require_once  IMP_BASE . '/lib/MIME/Contents.php';
 497      require_once  IMP_BASE . '/lib/MIME/Headers.php';
 498      $imp_contents = &IMP_Contents::singleton($index . IMP_IDX_SEP . $_SESSION['imp']['thismailbox']);
 499      $imp_headers = &new IMP_Headers($index);
 500  }
 501  $imp_folder = &IMP_Folder::singleton();
 502  
 503  /* Set the current time zone. */
 504  NLS::setTimeZone();
 505  
 506  /* Set the default charset & encoding.
 507   * $charset holds the charset to use when sending messages, $encoding the best
 508   * guessed charset offered to the user as the default value in the charset
 509   * dropdown list. */
 510  if ($prefs->isLocked('sending_charset')) {
 511      $charset = NLS::getEmailCharset();
 512  } else {
 513      $charset = Util::getFormData('charset');
 514  }
 515  $encoding = _getEncoding();
 516  
 517  /* Initialize the IMP_Compose:: object. */
 518  $oldMessageCacheID = Util::getFormData('messageCache');
 519  $imp_compose = &new IMP_Compose(array('cacheID' => $oldMessageCacheID));
 520  
 521  /* Is this a popup window? */
 522  $isPopup = (($prefs->getValue('compose_popup') || Util::getFormData('popup')) && $browser->hasFeature('javascript'));
 523  
 524  /* Determine the composition type - text or HTML.
 525     $rtemode is null if browser does not support it. */
 526  $rtemode = null;
 527  if ($browser->hasFeature('rte')) {
 528      $rtemode = false;
 529      if ($prefs->isLocked('compose_html')) {
 530          $rtemode = $prefs->getValue('compose_html');
 531      } else {
 532          $rtemode = Util::getFormData('rtemode');
 533          if (is_null($rtemode)) {
 534              $rtemode = $prefs->getValue('compose_html');
 535          } else {
 536              $oldrtemode = Util::getFormData('oldrtemode');
 537              $get_sig = false;
 538          }
 539      }
 540  }
 541  
 542  /* Load stationery. */
 543  if (!$prefs->isLocked('stationery')) {
 544      $stationery = null;
 545      $all_stationery = @unserialize($prefs->getValue('stationery', false));
 546      if (is_array($all_stationery)) {
 547          $all_stationery = String::convertCharset($all_stationery, $prefs->getCharset());
 548          $stationery_list = array();
 549          foreach ($all_stationery as $stationery_id => $stationery_choice) {
 550              if ($stationery_choice['t'] == 'plain' ||
 551                  ($stationery_choice['t'] == 'html' && $rtemode)) {
 552                  if ($rtemode && $stationery_choice['t'] == 'plain') {
 553                      require_once 'Horde/Text/Filter.php';
 554                      $stationery_choice['c'] = Text_Filter::Filter($stationery_choice['c'], 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null));
 555                  }
 556                  $stationery_list[$stationery_id] = $stationery_choice;
 557              }
 558          }
 559      } else {
 560          $stationery_list = null;
 561      }
 562  }
 563  
 564  /* Update the file attachment information. */
 565  if ($imp['file_upload']) {
 566      /* Only notify if we are reloading the compose screen. */
 567      $notify = ($actionID != 'send_message') && ($actionID != 'save_draft');
 568  
 569      $deleteList = Util::getPost('delattachments', array());
 570  
 571      /* Update the attachment information. */
 572      for ($i = 1; $i <= $imp_compose->numberOfAttachments(); $i++) {
 573          if (!in_array($i, $deleteList)) {
 574              $disposition = Util::getFormData('file_disposition_' . $i);
 575              $description = Util::getFormData('file_description_' . $i);
 576              $imp_compose->updateAttachment($i, array('disposition' => $disposition, 'description' => $description));
 577          }
 578      }
 579  
 580      /* Delete attachments. */
 581      if (!empty($deleteList)) {
 582          $filenames = $imp_compose->deleteAttachment($deleteList);
 583          if ($notify) {
 584              foreach ($filenames as $val) {
 585                  $notification->push(sprintf(_("Deleted the attachment \"%s\"."), MIME::decode($val)), 'horde.success');
 586              }
 587          }
 588      }
 589  
 590      /* Add new attachments. */
 591      for ($i = 1; $i <= count($_FILES); $i++) {
 592          $key = 'upload_' . $i;
 593          if (isset($_FILES[$key]) &&
 594              ($_FILES[$key]['error'] != 4)) {
 595              if ($_FILES[$key]['size'] == 0) {
 596                  $actionID = null;
 597                  $notification->push(sprintf(_("Did not attach \"%s\" as the file was empty."), $_FILES[$key]['name']), 'horde.warning');
 598              } else {
 599                  $result = $imp_compose->addUploadAttachment($key, Util::getFormData('upload_disposition_' . $i));
 600                  if (is_a($result, 'PEAR_Error')) {
 601                      /* Don't send message immediately if we hit an error. */
 602                      $actionID = null;
 603                      $notification->push($result, 'horde.error');
 604                  } elseif ($notify) {
 605                      $notification->push(sprintf(_("Added \"%s\" as an attachment."), $result), 'horde.success');
 606                  }
 607              }
 608          }
 609      }
 610  }
 611  
 612  /* Run through the action handlers. */
 613  $title = _("Message Composition");
 614  switch ($actionID) {
 615  case 'recompose':
 616      // Extract the stored form data.
 617      $formData = @unserialize($_SESSION['formData']);
 618      unset($_SESSION['formData']);
 619  
 620      if (!empty($formData['post'])) {
 621          $_POST = $formData['post'];
 622      }
 623      if (!empty($formData['get'])) {
 624          $_GET = $formData['get'];
 625      }
 626  
 627      $get_sig = false;
 628      break;
 629  
 630  case 'mailto':
 631      if (!empty($index)) {
 632          $header['to'] = '';
 633          if (Util::getFormData('mailto')) {
 634              $header['to'] = $imp_headers->getOb('toaddress', true);
 635          }
 636          if (empty($header['to'])) {
 637              ($header['to'] = MIME::addrArray2String($imp_headers->getOb('from'))) ||
 638              ($header['to'] = MIME::addrArray2String($imp_headers->getOb('reply_to')));
 639          }
 640          $title = _("Message Composition");
 641      }
 642      break;
 643  
 644  case 'draft':
 645      if (!empty($index)) {
 646          $mime_message = $imp_contents->rebuildMessage();
 647          $imp_compose->forwardMessage($imp_contents, $imp_headers);
 648          $res = $imp_compose->attachFilesFromMessage($imp_contents);
 649          if (!empty($res)) {
 650              foreach ($res as $val) {
 651                  $notification->push($val, 'horde.error');
 652              }
 653          }
 654  
 655          $body_text = null;
 656          $draft_mode = 'text';
 657          if (($rtemode !== null) &&
 658              ($mime_message->getType() == 'multipart/alternative')) {
 659              $type_map = $mime_message->contentTypeMap();
 660              $html_key = array_search('text/html', $type_map);
 661              if ($html_key !== false) {
 662                  $body_part = &$imp_contents->getDecodedMIMEPart($html_key);
 663                  $body_text = $body_part->getContents();
 664                  foreach ($imp_compose->getAttachments() as $key => $val) {
 665                      if ($val->getMIMEId() == $html_key) {
 666                          $imp_compose->deleteAttachment(++$key);
 667                          break;
 668                      }
 669                  }
 670                  $draft_mode = 'html';
 671              }
 672          }
 673  
 674          if ($rtemode !== null) {
 675              $rtemode = ($draft_mode == 'html');
 676          }
 677  
 678          if (is_null($body_text)) {
 679              $body_id = $imp_compose->getBodyId($imp_contents);
 680              $body_part = $mime_message->getPart($body_id);
 681              $body_text = $imp_compose->findBody($imp_contents);
 682          }
 683          $msg = "\n" . String::convertCharset($body_text, $body_part->getCharset());
 684  
 685          if ($rtemode && ($body_part->getType() != 'text/html')) {
 686              require_once 'Horde/Text/Filter.php';
 687              $msg = Text_Filter::filter($msg, 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null));
 688          }
 689  
 690          if (($fromaddr = $imp_headers->getOb('fromaddress'))) {
 691              $_GET['identity'] = $identity->getMatchingIdentity($fromaddr);
 692              $sent_mail_folder = $identity->getValue('sent_mail_folder', Util::getFormData('identity'));
 693          }
 694          $header['to'] = MIME::addrArray2String($imp_headers->getOb('to'));
 695          $header['cc'] = MIME::addrArray2String($imp_headers->getOb('cc'));
 696          $header['bcc'] = MIME::addrArray2String($imp_headers->getOb('bcc'));
 697          $header['subject'] = $imp_headers->getOb('subject', true);
 698  
 699          $title = _("Message Composition");
 700      }
 701      $get_sig = false;
 702      break;
 703  
 704  case 'compose_expand_addr':
 705      $header['to'] = _expandAddresses('to');
 706      $header['cc'] = _expandAddresses('cc');
 707      $header['bcc'] = _expandAddresses('bcc');
 708      $get_sig = false;
 709      break;
 710  
 711  case 'redirect_expand_addr':
 712      $header['to'] = _expandAddresses('to');
 713      $get_sig = false;
 714      break;
 715  
 716  case 'reply':
 717  case 'reply_all':
 718  case 'reply_list':
 719      if (!empty($index)) {
 720          /* Set the message_id and references headers. */
 721          if (($msg_id = $imp_headers->getOb('message_id'))) {
 722              $header['inreplyto'] = chop($msg_id);
 723              if (($header['references'] = $imp_headers->getOb('references'))) {
 724                  $header['references'] .= ' ' . $header['inreplyto'];
 725              } else {
 726                  $header['references'] = $header['inreplyto'];
 727              }
 728          }
 729  
 730          if ($actionID == 'reply') {
 731              ($header['to'] = Util::getFormData('to')) ||
 732              ($header['to'] = MIME::addrArray2String($imp_headers->getOb('reply_to'))) ||
 733              ($header['to'] = MIME::addrArray2String($imp_headers->getOb('from')));
 734          } elseif ($actionID == 'reply_all') {
 735              /* Filter out our own address from the addresses we reply to. */
 736              $me = array_keys($identity->getAllFromAddresses(true));
 737  
 738              /* Build the To: header. */
 739              $from_arr = $imp_headers->getOb('from');
 740              $to_arr = $imp_headers->getOb('reply_to');
 741              $reply = '';
 742              if (!empty($to_arr)) {
 743                  $reply = MIME::addrArray2String($to_arr);
 744              } elseif (!empty($from_arr)) {
 745                  $reply = MIME::addrArray2String($from_arr);
 746              }
 747              $header['to'] = MIME::addrArray2String(array_merge($to_arr, $from_arr));
 748              $me[] = IMP::bareAddress($header['to']);
 749  
 750              /* Build the Cc: header. */
 751              $cc_arr = $imp_headers->getOb('to');
 752              if (!empty($cc_arr) &&
 753                  ($reply != MIME::addrArray2String($cc_arr))) {
 754                  $cc_arr = array_merge($cc_arr, $imp_headers->getOb('cc'));
 755              } else {
 756                  $cc_arr = $imp_headers->getOb('cc');
 757              }
 758              $header['cc'] = MIME::addrArray2String($cc_arr, $me);
 759  
 760              /* Build the Bcc: header. */
 761              $header['bcc'] = MIME::addrArray2String($imp_headers->getOb('bcc') + $identity->getBccAddresses(), $me);
 762          } elseif ($actionID == 'reply_list') {
 763              $header['to'] = Util::getFormData('to');
 764          }
 765  
 766          $qfrom = MIME::addrArray2String($imp_headers->getOb('from'));
 767          if (empty($qfrom)) {
 768              $qfrom = '&lt;&gt;';
 769          }
 770  
 771          $mime_message = $imp_contents->getMIMEMessage();
 772          $encoding = _getEncoding($mime_message);
 773          $msg = $imp_compose->replyMessage($imp_contents, $qfrom, $imp_headers);
 774          if ($rtemode) {
 775              require_once 'Horde/Text/Filter.php';
 776              $msg = Text_Filter::filter($msg, 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null));
 777          }
 778  
 779          $header['subject'] = $imp_headers->getOb('subject', true);
 780          if (!empty($header['subject'])) {
 781              if (String::lower(String::substr($header['subject'], 0, 3)) != 're:') {
 782                  $header['subject'] = 'Re: ' . $header['subject'];
 783              }
 784          } else {
 785              $header['subject'] = 'Re: ';
 786          }
 787  
 788          if ($actionID == 'reply') {
 789              $title = _("Reply:") . ' ' . $header['subject'];
 790          } elseif ($actionID == 'reply_all') {
 791              $title = _("Reply to All:") . ' ' . $header['subject'];
 792          } elseif ($actionID == 'reply_list') {
 793              $title = _("Reply to List:") . ' ' . $header['subject'];
 794          }
 795  
 796          $reply_index = $index;
 797      }
 798      break;
 799  
 800  case 'forward':
 801      if (!empty($index)) {
 802          $mime_message = $imp_contents->rebuildMessage();
 803          $encoding = _getEncoding($mime_message);
 804          $msg = $imp_compose->forwardMessage($imp_contents, $imp_headers);
 805          if ($rtemode) {
 806              require_once 'Horde/Text/Filter.php';
 807              $msg = Text_Filter::filter($msg, 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null));
 808          }
 809  
 810          $res = $imp_compose->attachFilesFromMessage($imp_contents);
 811          if (!empty($res)) {
 812              foreach ($res as $val) {
 813                  $notification->push($val, 'horde.error');
 814              }
 815          }
 816  
 817          /* We need the Message-Id so we can log this event. */
 818          if (is_array($message_id = $imp_headers->getOb('message_id'))) {
 819              $message_id = reset($message_id);
 820          }
 821          $header['inreplyto'] = chop($message_id);
 822  
 823          $header['subject'] = $imp_headers->getOb('subject', true);
 824          if (!empty($header['subject'])) {
 825              $title = _("Forward:") . ' ' . $header['subject'];
 826              /* If the subject line already has signals indicating this
 827                 message is a forward, do not add an additional
 828                 signal. */
 829              $fwd_signal = false;
 830              foreach (array('fwd:', 'fw:', '(fwd)', '[fwd]') as $signal) {
 831                  if (stristr($header['subject'], $signal) !== false) {
 832                      $fwd_signal = true;
 833                      break;
 834                  }
 835              }
 836              if (!$fwd_signal) {
 837                  $header['subject'] = _("Fwd:") . ' ' . $header['subject'];
 838              }
 839          } else {
 840              $title = _("Forward");
 841              $header['subject'] = _("Fwd:");
 842          }
 843      }
 844      break;
 845  
 846  case 'redirect_compose':
 847      $title = _("Redirect this message");
 848      $rtemode = false;
 849      break;
 850  
 851  case 'redirect_send':
 852      $f_to = Util::getFormData('to', _getAddressList('to'));
 853      if (!empty($index) && $f_to) {
 854          $recipients = _recipientList(array($f_to));
 855          if (is_a($recipients, 'PEAR_Error')) {
 856              $notification->push($recipients, 'horde.error');
 857              $get_sig = false;
 858              break;
 859          }
 860          $recipients = implode(', ', $recipients);
 861  
 862          $imp_headers->buildHeaders(false);
 863          $imp_headers->addResentHeaders($identity->getFromAddress(), $f_to);
 864  
 865          /* We need to set the Return-Path header to the current user - see
 866             RFC 2821 [4.4]. */
 867          $imp_headers->removeHeader('return-path');
 868          $imp_headers->addHeader('Return-Path', $identity->getFromAddress());
 869  
 870          $bodytext = str_replace("\r\n", "\n", $imp_contents->getBody());
 871          $status = $imp_compose->sendMessage($recipients, $imp_headers, $bodytext, (isset($charset) ? $charset : $encoding));
 872          if (!is_a($status, 'PEAR_Error')) {
 873              $entry = sprintf("%s Redirected message sent to %s from %s",
 874                               $_SERVER['REMOTE_ADDR'], $recipients, $imp['user']);
 875              Horde::logMessage($entry, __FILE__, __LINE__, PEAR_LOG_INFO);
 876  
 877              /* Store history information. */
 878              if (!empty($conf['maillog']['use_maillog'])) {
 879                  require_once  IMP_BASE . '/lib/Maillog.php';
 880                  IMP_Maillog::log('redirect', $imp_headers->getOb('message_id'), $recipients);
 881              }
 882  
 883              if ($isPopup) {
 884                  if ($prefs->getValue('compose_confirm')) {
 885                      $notification->push(_("Message redirected successfully."), 'horde.success');
 886                      _popupSuccess();
 887                  } else {
 888                      Util::closeWindowJS();
 889                  }
 890              } else {
 891                  if ($prefs->getValue('compose_confirm')) {
 892                      $notification->push(_("Message redirected successfully."), 'horde.success');
 893                  }
 894                  header('Location: ' . _mailboxReturnURL(false));
 895              }
 896              exit;
 897          } else {
 898              Horde::logMessage($status->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
 899          }
 900          $actionID = 'redirect_compose';
 901          $notification->push(_("Redirecting failed."), 'horde.error');
 902      }
 903      break;
 904  
 905  case 'send_message':
 906      $f_cc = $f_bcc = null;
 907  
 908      $f_to = _getAddressList('to');
 909      if ($conf['compose']['allow_cc']) {
 910          $f_cc = _getAddressList('cc');
 911      }
 912      if ($conf['compose']['allow_bcc']) {
 913          $f_bcc = _getAddressList('bcc');
 914      }
 915  
 916      /* We need at least one recipient & RFC 2822 requires that no
 917       * 8-bit characters can be in the address fields. */
 918      $recipientArray = _recipientList(array($f_to, $f_cc, $f_bcc));
 919      if (is_a($recipientArray, 'PEAR_Error')) {
 920          $notification->push($recipientArray, 'horde.error');
 921          $get_sig = false;
 922          break;
 923      }
 924      $recipients = implode(', ', $recipientArray);
 925  
 926      /* Get identity information now as it is needed for some of the encryption
 927       * code. */
 928      $identity_form = Util::getFormData('identity');
 929      $from = $identity->getFromLine($identity_form, Util::getFormData('from'));
 930      $barefrom = IMP::bareAddress($from);
 931      $identity->setDefault($identity_form);
 932      $replyto = $identity->getValue('replyto_addr');
 933  
 934      /* Set up the base message now. */
 935      $body = _baseMessage($imp_compose, $charset);
 936      if (is_a($body, 'PEAR_Error')) {
 937          $notification->push($body, 'horde.error');
 938          break;
 939      }
 940  
 941      /* Prepare the array of messages to send out.  May be more than one if
 942       * we are encrypting for multiple recipients are storing an encrypted
 943       * message locally. */
 944      $messagesToSend = array();
 945  
 946      /* Do encryption. */
 947      $encrypt = Util::getFormData('encrypt_options');
 948      $usePGP = ($prefs->getValue('use_pgp') && !empty($conf['utils']['gnupg']));
 949      $useSMIME = $prefs->getValue('use_smime');
 950      $multiple_pgp_msg = false;
 951  
 952      if ($usePGP &&
 953          in_array($encrypt, array(IMP_PGP_ENCRYPT, IMP_PGP_SIGNENC))) {
 954          if (empty($imp_pgp)) {
 955              require_once  IMP_BASE .'/lib/Crypt/PGP.php';
 956              $imp_pgp = &new IMP_PGP();
 957          }
 958          if (empty($imp_pgp->multipleRecipientEncryption)) {
 959              $multiple_pgp_msg = true;
 960          }
 961      }
 962  
 963      if ($multiple_pgp_msg ||
 964          ($useSMIME &&
 965           in_array($encrypt, array(IMP_SMIME_ENCRYPT, IMP_SMIME_SIGNENC)))) {
 966          /* Must encrypt & send the message one recipient at a time. */
 967          foreach ($recipientArray as $val) {
 968              $res = _createMimeMessage(array($val), $body);
 969              if (is_a($res, 'PEAR_Error')) {
 970                  $get_sig = false;
 971                  $notification->push($res, 'horde.error');
 972                  break 2;
 973              }
 974              $messagesToSend[] = $res;
 975          }
 976  
 977          /* Must target the encryption for the sender before saving message in
 978           * sent-mail. */
 979          $messageToSave = _createMimeMessage(array($from), $body);
 980          if (is_a($messageToSave, 'PEAR_Error')) {
 981              $get_sig = false;
 982              $notification->push($messageToSave, 'horde.error');
 983              break;
 984          }
 985      } else {
 986          /* No encryption - can send in clear-text all at once. */
 987          $res = _createMimeMessage($recipientArray, $body);
 988          if (is_a($res, 'PEAR_Error')) {
 989              $get_sig = false;
 990              $notification->push($res, 'horde.error');
 991              break;
 992          }
 993          $messagesToSend[] = $messageToSave = $res;
 994      }
 995  
 996      /* Initalize a header object for the outgoing message. */
 997      require_once  IMP_BASE . '/lib/MIME/Headers.php';
 998      $msg_headers = &new IMP_Headers();
 999  
1000      /* Add a Received header for the hop from browser to server. */
1001      $msg_headers->addReceivedHeader();
1002      $msg_headers->addMessageIdHeader();
1003  
1004      /* Add the X-Priority header, if requested. This appears here since
1005         this is the "general" location that other mail clients insert
1006         this header. */
1007      if ($prefs->getValue('set_priority') &&
1008          Util::getFormData('x_priority')) {
1009          $msg_headers->addHeader('X-Priority', Util::getFormData('x_priority'));
1010      }
1011  
1012      $msg_headers->addHeader('Date', date('r'));
1013  
1014      /* Add Return Receipt Headers. */
1015      if ($conf['compose']['allow_receipts']) {
1016          if (Util::getFormData('request_read_receipt')) {
1017              require_once 'Horde/MIME/MDN.php';
1018              $mdn = &new MIME_MDN();
1019              $mdn->addMDNRequestHeaders($msg_headers, $barefrom);
1020          }
1021      }
1022  
1023      $browser_charset = NLS::getCharset();
1024  
1025      $msg_headers->addHeader('From', String::convertCharset($from, $browser_charset, $charset));
1026  
1027      if (!empty($replyto) && ($replyto != $barefrom)) {
1028          $msg_headers->addHeader('Reply-to', String::convertCharset($replyto, $browser_charset, $charset));
1029      }
1030      if (!empty($f_to)) {
1031          $msg_headers->addHeader('To', String::convertCharset($f_to, $browser_charset, $charset));
1032      } elseif (empty($f_to) && empty($f_cc)) {
1033          $msg_headers->addHeader('To', 'undisclosed-recipients:;');
1034      }
1035      if (!empty($f_cc)) {
1036          $msg_headers->addHeader('Cc', String::convertCharset($f_cc, $browser_charset, $charset));
1037      }
1038      $msg_headers->addHeader('Subject', String::convertCharset(Util::getFormData('subject', ''), $browser_charset, $charset));
1039  
1040      /* Add necessary headers for replies. */
1041      $reply_type = Util::getFormData('reply_type');
1042      $irt = Util::getFormData('in_reply_to');
1043      if ($reply_type == 'reply') {
1044          if ($ref = Util::getFormData('references')) {
1045              $msg_headers->addHeader('References', implode(' ', preg_split('|\s+|', trim($ref))));
1046          }
1047          if ($irt) {
1048              $msg_headers->addHeader('In-Reply-To', $irt);
1049          }
1050      }
1051  
1052      /* Send the messages out now. */
1053      foreach ($messagesToSend as $val) {
1054          $headers = &Util::cloneObject($msg_headers);
1055          $headers->addMIMEHeaders($val['msg']);
1056          $res = $imp_compose->sendMessage($val['to'], $headers, $val['msg'], $charset);
1057          if (is_a($res, 'PEAR_Error')) {
1058              /* Unsuccessful send. */
1059              Horde::logMessage($res->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
1060              $notification->push(sprintf(_("There was an error sending your message: %s"), $res->getMessage()), 'horde.error');
1061              $get_sig = false;
1062              break 2;
1063          }
1064      }
1065  
1066      $sent_saved = true;
1067  
1068      /* Log the reply. */
1069      if ($reply_type && $irt) {
1070          if (!empty($conf['maillog']['use_maillog'])) {
1071              require_once  IMP_BASE . '/lib/Maillog.php';
1072              IMP_Maillog::log($reply_type, $irt, $recipients);
1073          }
1074  
1075          if ($reply_index && ($reply_type == 'reply')) {
1076              /* Make sure to set the IMAP reply flag. */
1077              require_once  IMP_BASE . '/lib/Message.php';
1078              $imp_message = &IMP_Message::singleton();
1079              $flag = array($_SESSION['imp']['thismailbox'] => array($reply_index));
1080              $imp_message->flag('\\ANSWERED', $flag);
1081          }
1082      }
1083  
1084      $entry = sprintf("%s Message sent to %s from %s", $_SERVER['REMOTE_ADDR'], $recipients, $imp['user']);
1085      Horde::logMessage($entry, __FILE__, __LINE__, PEAR_LOG_INFO);
1086  
1087      /* Delete the attachment data. */
1088      $num_attachments = $imp_compose->numberOfAttachments();
1089      $imp_compose->deleteAllAttachments();
1090  
1091      /* Should we save this message in the sent mail folder? */
1092      if ($smf = Util::getFormData('sent_mail_folder')) {
1093          $sent_mail_folder = $smf;
1094      }
1095      if (!empty($sent_mail_folder) &&
1096          ((!$prefs->isLocked('save_sent_mail') &&
1097            Util::getFormData('save_sent_mail')) ||
1098           ($prefs->isLocked('save_sent_mail') &&
1099            $prefs->getValue('save_sent_mail')))) {
1100  
1101          $mime_message = $messageToSave['msg'];
1102          $msg_headers->addMIMEHeaders($mime_message);
1103  
1104          /* Keep Bcc: headers on saved messages. */
1105          if (!empty($f_bcc)) {
1106              $msg_headers->addHeader('Bcc', $f_bcc);
1107          }
1108  
1109          /* Loop through the envelope and add headers. */
1110          $headerArray = $mime_message->encode($msg_headers->toArray(), $charset);
1111          foreach ($headerArray as $key => $value) {
1112              $msg_headers->addHeader($key, $value);
1113          }
1114          $fcc = $msg_headers->toString();
1115  
1116          /* Strip attachments if requested. */
1117          $save_attach = $prefs->getValue('save_attachments');
1118          if (($save_attach == 'never') ||
1119              ((strpos($save_attach, 'prompt') === 0) &&
1120               (Util::getFormData('save_attachments_select') == 0))) {
1121              for ($i = 1; $i <= $num_attachments; $i++) {
1122                  $oldPart = &$mime_message->getPart($i + 1);
1123                  if ($oldPart !== false) {
1124                      $replace_part = &new MIME_Part('text/plain');
1125                      $replace_part->setCharset($charset);
1126                      $replace_part->setContents('[' . _("Attachment stripped: Original attachment type") . ': "' . $oldPart->getType() . '", ' . _("name") . ': "' . $oldPart->getName(true, true) . '"]', '8bit');
1127                      $mime_message->alterPart($i + 1, $replace_part);
1128                  }
1129              }
1130          }
1131  
1132          /* Add the body text to the message string. */
1133          $fcc .= $mime_message->toString();
1134  
1135          /* Make absolutely sure there are no bare newlines. */
1136          $fcc = preg_replace("|([^\r])\n|", "\\1\r\n", $fcc);
1137          $fcc = str_replace("\n\n", "\n\r\n", $fcc);
1138  
1139          if (!$imp_folder->exists($sent_mail_folder)) {
1140              $imp_folder->create($sent_mail_folder, $prefs->getValue('subscribe'));
1141          }
1142          if (!@imap_append($imp['stream'], IMP::serverString($sent_mail_folder), $fcc, '\\Seen')) {
1143              $notification->push(sprintf(_("Message sent successfully, but not saved to %s"), IMP::displayFolder($sent_mail_folder)));
1144              $sent_saved = false;
1145          }
1146      }
1147  
1148      /* Save recipients to address book? */
1149      if ($prefs->getValue('save_recipients') &&
1150          $registry->hasMethod('contacts/import') &&
1151          $registry->hasMethod('contacts/search')) {
1152  
1153          $abook = $prefs->getValue('add_source');
1154          if (!empty($abook)) {
1155              require_once 'Mail/RFC822.php';
1156              $parser = &new Mail_RFC822();
1157              $recipientArray = $parser->parseAddressList(MIME::encodeAddress($recipients, null, $_SESSION['imp']['maildomain']));
1158  
1159              /* Filter out anyone that matches an email address already
1160               * in the address book. */
1161              $emails = array();
1162              foreach ($recipientArray as $recipient) {
1163                  $emails[] = $recipient->mailbox . '@' . $recipient->host;
1164              }
1165              $results = $registry->call('contacts/search', array($emails, array($abook), array($abook => array('email'))));
1166  
1167              foreach ($recipientArray as $recipient) {
1168                  /* Skip email addresses that already exist in the
1169                   * add_source. */
1170                  if (isset($results[$recipient->mailbox . '@' . $recipient->host]) &&
1171                      count($results[$recipient->mailbox . '@' . $recipient->host])) {
1172                      continue;
1173                  }
1174  
1175                  /* Remove surrounding quotes and make sure that $name
1176                   * is non-empty. */
1177                  $name = trim($recipient->personal);
1178                  if (preg_match('/^(["\']).*\1$/', $name)) {
1179                      $name = substr($name, 1, -1);
1180                  }
1181                  if (empty($name)) {
1182                      $name = $recipient->mailbox;
1183                  }
1184                  $name = MIME::decode($name, $browser_charset);
1185  
1186                  $result = $registry->call('contacts/import', array(array('name' => $name, 'email' => $recipient->mailbox . '@' . $recipient->host),
1187                                                                     'array', $abook));
1188                  if (is_a($result, 'PEAR_Error')) {
1189                      if ($result->getCode() == 'horde.error') {
1190                          $notification->push($result, $result->getCode());
1191                      }
1192                  } else {
1193                      $notification->push(sprintf(_("Entry \"%s\" was successfully added to the address book"), $name), 'horde.success');
1194                  }
1195              }
1196          }
1197      }
1198  
1199      if ($isPopup) {
1200          if ($prefs->getValue('compose_confirm') || !$sent_saved) {
1201              if ($sent_saved) {
1202                  $notification->push(_("Message sent successfully."), 'horde.success');
1203              }
1204              _popupSuccess();
1205          } else {
1206              Util::closeWindowJS();
1207          }
1208      } else {
1209          if ($prefs->getValue('compose_confirm') && $sent_saved) {
1210              $notification->push(_("Message sent successfully."), 'horde.success');
1211          }
1212          header('Location: ' . _mailboxReturnURL(false));
1213      }
1214      exit;
1215  
1216  case 'save_draft':
1217      $drafts_folder = IMP::folderPref($prefs->getValue('drafts_folder'), true);
1218      if (!empty($drafts_folder)) {
1219          require_once 'Horde/MIME/Message.php';
1220          $mime = &new MIME_Message($imp['maildomain']);
1221  
1222          /* We need to make sure we add "\r\n" after every line for
1223           * imap_append() - some servers require it (e.g. Cyrus). */
1224          $mime->setEOL(MIME_PART_RFC_EOL);
1225  
1226          /* Set up the base message now. */
1227          $body = _baseMessage($imp_compose, $charset, false);
1228          if (is_a($body, 'PEAR_Error')) {
1229              $notification->push($res, 'horde.error');
1230              break;
1231          }
1232  
1233          $mime->addPart($body);
1234          $body = $mime->toString();
1235  
1236          $from = $identity->getFromLine(Util::getFormData('identity'), Util::getFormData('from'));
1237  
1238          /* Initalize a header object for the draft. */
1239          require_once  IMP_BASE . '/lib/MIME/Headers.php';
1240          $draft_headers = &new IMP_Headers();
1241  
1242          $draft_headers->addHeader('Date', date('r'));
1243          if (!empty($from)) {
1244              $draft_headers->addHeader('From', $from);
1245          }
1246          if (($header['to'] = Util::getFormData('to'))) {
1247              $draft_headers->addHeader('To', MIME::encodeAddress(_formatAddr($header['to']), null, $imp['maildomain']));
1248          }
1249          if (($header['cc'] = Util::getFormData('cc'))) {
1250              $draft_headers->addHeader('Cc', MIME::encodeAddress(_formatAddr($header['cc']), null, $imp['maildomain']));
1251          }
1252          if (($header['bcc'] = Util::getFormData('bcc'))) {
1253              $draft_headers->addHeader('Bcc', MIME::encodeAddress(_formatAddr($header['bcc']), null, $imp['maildomain']));
1254          }
1255          if (($sub = Util::getFormData('subject'))) {
1256              $draft_headers->addHeader('Subject', MIME::encode($sub, NLS::getCharset()));
1257          }
1258          if (isset($mime)) {
1259              $draft_headers->addMIMEHeaders($mime);
1260          }
1261  
1262          $body = $draft_headers->toString() . $body;
1263  
1264          // Make absolutely sure there are no bare newlines.
1265          $body = preg_replace("|([^\r])\n|", "\\1\r\n", $body);
1266          $body = str_replace("\n\n", "\n\r\n", $body);
1267  
1268          if ($prefs->getValue('unseen_drafts')) {
1269              $append_flags = '\\Draft';
1270          } else {
1271              $append_flags = '\\Draft \\Seen';
1272          }
1273  
1274          $draft_success = false;
1275  
1276          if ($imp_folder->exists($drafts_folder)) {
1277              $draft_success = true;
1278          } elseif ($imp_folder->create($drafts_folder, $prefs->getValue('subscribe'))) {
1279              $draft_success = true;
1280          }
1281  
1282          if ($draft_success) {
1283              if (!@imap_append($imp['stream'], IMP::serverString($drafts_folder), $body, $append_flags)) {
1284                  $notification->push(sprintf(_("Saving the draft failed. This is what the server said: %s"), imap_last_error()), 'horde.error');
1285              } elseif ($prefs->getValue('close_draft')) {
1286                  if ($isPopup) {
1287                      Util::closeWindowJS();
1288                  } else {
1289                      header('Location: ' . _mailboxReturnURL(false));
1290                  }
1291                  exit;
1292              } else {
1293                  $notification->push(sprintf(_("The draft has been saved to the \"%s\" folder."),
1294                                              IMP::displayFolder($drafts_folder)));
1295                  $get_sig = false;
1296                  break;
1297              }
1298          }
1299      }
1300      $get_sig = false;
1301      $notification->push(_("There was an error saving this message as a draft."), 'horde.error');
1302      break;
1303  
1304  case 'fwd_digest':
1305      $indices = Util::getFormData('fwddigest');
1306      if (!empty($indices)) {
1307          require_once  IMP_BASE . '/lib/MIME/Contents.php';
1308          $msglist = unserialize(urldecode($indices));
1309          foreach ($msglist as $index) {
1310              if (strstr($index, IMP_IDX_SEP)) {
1311                  require_once  IMP_BASE . '/lib/base.php';
1312                  $imp_imap = &IMP_IMAP::singleton();
1313                  list($index, $mailbox) = explode(IMP_IDX_SEP, $index);
1314                  $imp_imap->changeMbox($mailbox);
1315              } else {
1316                  $mailbox = $_SESSION['imp']['thismailbox'];
1317              }
1318              $part = &new MIME_Part('message/rfc822');
1319              $contents = &IMP_Contents::singleton($index . IMP_IDX_SEP . $mailbox);
1320              $digest_headers = &$contents->getHeaderOb();
1321              if (!($name = $digest_headers->getOb('subject', true))) {
1322                  $name = _("[No Subject]");
1323              }
1324              $part->setName($name);
1325              $part->setContents($contents->fullMessageText());
1326              $res = $imp_compose->addMIMEPartAttachment($part);
1327              if (is_a($res, 'PEAR_Error')) {
1328                  $notification->push($res, 'horde.error');
1329              }
1330          }
1331          if (count($msglist) == 1) {
1332              $header['subject'] = _("Fwd: ") . $name;
1333          } else {
1334              $header['subject'] = sprintf(_("Fwd: %u Forwarded Messages"), count($msglist));
1335          }
1336      }
1337      break;
1338  
1339  case 'cancel_compose':
1340      $imp_compose->deleteAllAttachments();
1341      if ($isPopup) {
1342          Util::closeWindowJS();
1343      } else {
1344          header('Location: ' . _mailboxReturnURL(false));
1345      }
1346      exit;
1347  
1348  case 'spell_check_cancel':
1349      $msg = "\n" . Util::getFormData('message');
1350      $expanded = Util::getFormData('to_list');
1351      if (!empty($expanded)) {
1352          $header['to'] = _expandAddresses('to');
1353          $header['cc'] = _expandAddresses('cc');
1354          $header['bcc'] = _expandAddresses('bcc');
1355      }
1356      $get_sig = false;
1357      break;
1358  
1359  case 'spell_check_done':
1360      $msg = "\n";
1361      $msg .= Util::getFormData('newmsg');
1362      $msg .= Util::getFormData('currmsg');
1363      $expanded = Util::getFormData('to_list');
1364      if (!empty($expanded)) {
1365          $header['to'] = _expandAddresses('to');
1366          $header['cc'] = _expandAddresses('cc');
1367          $header['bcc'] = _expandAddresses('bcc');
1368      }
1369      $get_sig = false;
1370      break;
1371  
1372  case 'spell_check':
1373  case 'spell_check_send':
1374  case 'spell_check_forward':
1375      require  IMP_BASE . '/spelling.php';
1376      break;
1377  
1378  case 'selectlist_process':
1379      $select_id = Util::getFormData('selectlist_selectid');
1380      if (!empty($select_id)) {
1381          if ($registry->hasMethod('files/selectlistResults') &&
1382              $registry->hasMethod('files/returnFromSelectlist')) {
1383              $filelist = $registry->call('files/selectlistResults', array($select_id));
1384              if ($filelist && !is_a($filelist, 'PEAR_Error')) {
1385                  $i = 0;
1386                  foreach ($filelist as $val) {
1387                      $data = $registry->call('files/returnFromSelectlist', array($select_id, $i++));
1388                      if ($data && !is_a($data, 'PEAR_Error')) {
1389                          $part = new MIME_Part();
1390                          $part->setContents($data);
1391                          $part->setName(reset($val));
1392                          $res = $imp_compose->addMIMEPartAttachment($part);
1393                          if (is_a($res, 'PEAR_Error')) {
1394                              $notification->push($res, 'horde.error');
1395                          }
1396                      }
1397                  }
1398              }
1399          }
1400      }
1401      break;
1402  
1403  case 'change_stationery':
1404      if (!$prefs->isLocked('stationery')) {
1405          $stationery = Util::getFormData('stationery');
1406          if (strlen($stationery)) {
1407              $stationery = (int)$stationery;
1408              $stationery_content = $stationery_list[$stationery]['c'];
1409              $msg = Util::getFormData('message', '');
1410              if (strpos($stationery_content, '%s') !== false) {
1411  
1412                  if (!is_null($selected_identity = Util::getFormData('identity'))) {
1413                      $sig = $identity->getSignature($selected_identity);
1414                  } else {
1415                      $sig = $identity->getSignature();
1416                  }
1417                  if ($rtemode) {
1418                      require_once 'Horde/Text/Filter.php';
1419                      $sig = Text_Filter::filter($sig, 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null));
1420                      $stationery_content = Text_Filter::filter($stationery_content, 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null));
1421                  }
1422                  $msg = str_replace(array("\r\n", $sig), array("\n", ''), $msg);
1423                  $stationery_content = str_replace('%s', $sig, $stationery_content);
1424              }
1425              if (strpos($stationery_content, '%c') === false) {
1426                  $msg .= $stationery_content;
1427              } else {
1428                  $msg = str_replace('%c', $msg, $stationery_content);
1429              }
1430          }
1431      }
1432      $get_sig = false;
1433      break;
1434  
1435  case 'add_attachment':
1436      $get_sig = false;
1437      break;
1438  
1439  }
1440  
1441  if ($rtemode) {
1442      require_once 'Horde/Editor.php';
1443      $editor = &Horde_Editor::singleton('htmlarea', array('id' => 'message'));
1444  }
1445  
1446  /* Get the message cache ID. */
1447  $messageCacheID = $imp_compose->getMessageCacheId();
1448  
1449  /* Has this page been reloaded? */
1450  $reloaded = Util::getFormData('reloaded');
1451  
1452  /* Set the 'save_sent_mail' checkbox for the form. */
1453  if ($reloaded) {
1454      $ssm_check = Util::getFormData('save_sent_mail') == 'on';
1455  } else {
1456      $ssm_check = $identity->saveSentmail(Util::getFormData('identity'));
1457  }
1458  
1459  if ($browser->isBrowser('msie')) {
1460      Horde::addScriptFile('ieEscGuard.js', 'imp', true);
1461  }
1462  require IMP_TEMPLATES . '/common-header.inc';
1463  
1464  if ($isPopup) {
1465      /* If the attachments cache is not empty, we must reload this page
1466       * and delete the attachments. */
1467      if ($messageCacheID) {
1468          $url = Util::addParameter(Horde::selfUrl(), array('actionID' => 'cancel_compose', 'messageCache' => $messageCacheID, 'popup' => 1), null, false);
1469          $cancel_js = 'self.location.href=\'' . $url . '\';';
1470      } else {
1471          $cancel_js = 'self.close();';
1472      }
1473  } else {
1474      /* If the attachments cache is not empty, we must reload this page and
1475         delete the attachments. */
1476      if ($messageCacheID) {
1477          $url = Util::addParameter(_mailboxReturnURL(true, Horde::selfUrl()), array('actionID' => 'cancel_compose', 'messageCache' => $messageCacheID), null, false);
1478          $cancel_js = 'window.location = \'' . $url . '\';';
1479      } else {
1480          $cancel_js = 'window.location = \'' . _mailboxReturnURL(true) . '\';';
1481      }
1482      require IMP_TEMPLATES . '/menu.inc';
1483  }
1484  
1485  $select_list = $identity->getSelectList();
1486  
1487  if (Util::getFormData('from') || $prefs->isLocked('default_identity')) {
1488      $from = $identity->getFromLine(Util::getFormData('identity'), Util::getFormData('from'));
1489  } else {
1490      $from_selected = Util::getFormData('identity');
1491      if (isset($from_selected)) {
1492          $identity->setDefault($from_selected);
1493      }
1494  }
1495  
1496  /* Grab any data that we were supplied with. */
1497  if (empty($msg)) {
1498      $msg = Util::getFormData('message', '');
1499      if ($browser->hasQuirk('double_linebreak_textarea')) {
1500          $msg = preg_replace('/(\r?\n){3}/', '$1', $msg);
1501      }
1502      $msg = "\n" . $msg;
1503  
1504      /* Convert from Text -> HTML or vice versa if RTE mode changed. */
1505      if (isset($oldrtemode) && ($oldrtemode != $rtemode)) {
1506          require_once 'Horde/Text/Filter.php';
1507          if ($rtemode) {
1508              $msg = Text_Filter::filter($msg, 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null));
1509          } else {
1510              $msg = Text_Filter::filter($msg, 'html2text');
1511          }
1512      }
1513  }
1514  
1515  /* If this is the first page load for this compose item, add auto BCC
1516   * addresses. */
1517  if (empty($reloaded) && ($actionID != 'draft')) {
1518      $header['bcc'] = MIME::addrArray2String($identity->getBccAddresses());
1519  }
1520  
1521  foreach (array('to', 'cc', 'bcc', 'subject') as $val) {
1522      if (empty($header[$val])) {
1523          $header[$val] = Util::getFormData($val, _getAddressList($val));
1524      }
1525  }
1526  
1527  $all_sigs = $identity->getAllSignatures();
1528  foreach ($all_sigs as $ident => $sig) {
1529      $identities[$ident] = array($sig,
1530                                  $identity->getValue('sig_first', $ident),
1531                                  $identity->getValue('sent_mail_folder', $ident),
1532                                  $identity->saveSentmail($ident),
1533                                  MIME::addrArray2String($identity->getBccAddresses($ident)));
1534  }
1535  $sig = $identity->getSignature();
1536  
1537  if ($get_sig && isset($msg) && !empty($sig)) {
1538      if ($rtemode) {
1539          require_once 'Horde/Text/Filter.php';
1540          $sig = '<p>' . Text_Filter::filter(trim($sig), 'text2html', array('parselevel' => TEXT_HTML_MICRO_LINKURL, 'class' => null, 'callback' => null)) . '</p>';
1541      }
1542  
1543      if ($identity->getValue('sig_first')) {
1544          $msg = "\n" . $sig . $msg;
1545      } else {
1546          $msg .= "\n" . $sig;
1547      }
1548  }
1549  
1550  /* Define some variables used in the templates. */
1551  $timeout = ini_get('session.gc_maxlifetime');
1552  
1553  /* Reload nls.php to get the translated charset names. */
1554  require HORDE_BASE . '/config/nls.php';
1555  
1556  switch ($actionID) {
1557  case 'redirect_compose':
1558  case 'redirect_expand_addr':
1559      $mailbox = Util::getFormData('thismailbox', $imp['mailbox']);
1560      require_once IMP_TEMPLATES . '/compose/compose_expand.js';
1561      require IMP_TEMPLATES . '/compose/redirect.inc';
1562      break;
1563  
1564  case 'spell_check':
1565  case 'spell_check_send':
1566  case 'spell_check_forward':
1567      require_once IMP_TEMPLATES . '/compose/spelling.js';
1568      require IMP_TEMPLATES . '/compose/spelling.inc';
1569      break;
1570  
1571  default:
1572      /* We need to define $num_attachments and $upload_list as it is used in
1573         both compose.inc and attachments.js. */
1574      if ($imp['file_upload']) {
1575          $attachments = $imp_compose->additionalAttachmentsAllowed();
1576      }
1577  
1578      require_once IMP_TEMPLATES . '/compose/compose.js';
1579      require_once IMP_TEMPLATES . '/compose/compose_expand.js';
1580      require IMP_TEMPLATES . '/compose/compose.inc';
1581  
1582      /* Insert javascript code. */
1583      if ($imp['file_upload']) {
1584          require_once IMP_TEMPLATES . '/compose/attachments.js';
1585      }
1586      break;
1587  }
1588  
1589  /* Open the passphrase window here. */
1590  if ($pgp_passphrase_dialog) {
1591      Horde::addScriptFile('popup.js');
1592      echo '<script type="text/javascript">' . $imp_pgp->getJSOpenWinCode('open_passphrase_dialog', "opener.focus();opener.document.compose.actionID.value='send_message';opener.uniqSubmit();") . '</script>';
1593  } elseif ($smime_passphrase_dialog) {
1594      Horde::addScriptFile('popup.js');
1595      echo '<script type="text/javascript">' . $imp_smime->getJSOpenWinCode('open_passphrase_dialog', "opener.focus();opener.document.compose.actionID.value='send_message';opener.uniqSubmit();") . '</script>';
1596  }
1597  
1598  require $registry->get('templates', 'horde') . '/common-footer.inc';


Généré le : Thu Nov 29 12:30:07 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics