[ Index ] |
|
Code source de IMP H3 (4.1.5) |
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 = '<>'; 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';
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 12:30:07 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |