1182 lines
45 KiB
PHP
1182 lines
45 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 1999-2017 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file COPYING for license information (GPL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/gpl.
|
|
*
|
|
* @category Horde
|
|
* @copyright 1999-2017 Horde LLC
|
|
* @license http://www.horde.org/licenses/gpl21 GPL
|
|
* @package IMP
|
|
*/
|
|
|
|
/**
|
|
* Compose page for the basic view.
|
|
*
|
|
* Copyright 1999-2017 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file COPYING for license information (GPL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/gpl.
|
|
*
|
|
* @author Chuck Hagenbuch <chuck@horde.org>
|
|
* @author Michael Slusarz <slusarz@horde.org>
|
|
* @category Horde
|
|
* @copyright 1999-2017 Horde LLC
|
|
* @license http://www.horde.org/licenses/gpl21 GPL
|
|
* @package IMP
|
|
*/
|
|
class IMP_Basic_Compose extends IMP_Basic_Base
|
|
{
|
|
/**
|
|
*/
|
|
protected function _init()
|
|
{
|
|
global $browser, $injector, $notification, $page_output, $prefs, $registry, $session;
|
|
|
|
/* Mailto link handler: redirect based on current view. */
|
|
if ($this->vars->actionID == 'mailto_link') {
|
|
switch ($registry->getView()) {
|
|
case Horde_Registry::VIEW_DYNAMIC:
|
|
IMP_Dynamic_Compose::url()->add($_GET)->redirect();
|
|
exit;
|
|
|
|
case Horde_Registry::VIEW_MINIMAL:
|
|
IMP_Minimal_Compose::url()->add($_GET)->redirect();
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/* The message headers and text. */
|
|
$header = array();
|
|
$msg = '';
|
|
|
|
$redirect = $resume = $spellcheck = false;
|
|
$oldrtemode = $rtemode = null;
|
|
|
|
/* Is this a popup window? */
|
|
if ($isPopup = ($prefs->getValue('compose_popup') || $this->vars->popup)) {
|
|
$page_output->topbar = $page_output->sidebar = false;
|
|
}
|
|
|
|
/* Set the current identity. */
|
|
$identity = $injector->getInstance('IMP_Identity');
|
|
if (!$prefs->isLocked('default_identity') &&
|
|
!is_null($this->vars->identity)) {
|
|
$identity->setDefault($this->vars->identity);
|
|
}
|
|
|
|
if ($this->vars->actionID) {
|
|
switch ($this->vars->actionID) {
|
|
case 'draft':
|
|
case 'editasnew':
|
|
case 'forward_attach':
|
|
case 'forward_auto':
|
|
case 'forward_body':
|
|
case 'forward_both':
|
|
case 'fwd_digest':
|
|
case 'mailto':
|
|
case 'mailto_link':
|
|
case 'reply':
|
|
case 'reply_all':
|
|
case 'reply_auto':
|
|
case 'reply_list':
|
|
case 'redirect_compose':
|
|
case 'template':
|
|
case 'template_edit':
|
|
case 'template_new':
|
|
/* These are all safe actions that might be invoked without a
|
|
* token. */
|
|
break;
|
|
|
|
default:
|
|
try {
|
|
$session->checkToken($this->vars->compose_requestToken);
|
|
} catch (Horde_Exception $e) {
|
|
$notification->push($e);
|
|
$this->vars->actionID = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Check for duplicate submits. */
|
|
if ($reload = $this->vars->compose_formToken) {
|
|
try {
|
|
$session->checkNonce($reload);
|
|
} catch (Horde_Exception $e) {
|
|
$notification->push(_("You have already submitted this page."), 'horde.error');
|
|
$this->vars->actionID = null;
|
|
}
|
|
}
|
|
|
|
/* Determine if compose mode is disabled. */
|
|
$compose_disable = !IMP_Compose::canCompose();
|
|
|
|
/* Determine if mailboxes are readonly. */
|
|
$draft = IMP_Mailbox::getPref(IMP_Mailbox::MBOX_DRAFTS);
|
|
$readonly_drafts = $draft && $draft->readonly;
|
|
|
|
$sent_mail = $identity->getValue(IMP_Mailbox::MBOX_SENT);
|
|
if (!$sent_mail) {
|
|
$readonly_sentmail = $save_sent_mail = false;
|
|
} elseif ($sent_mail->readonly) {
|
|
$readonly_sentmail = true;
|
|
$save_sent_mail = false;
|
|
} else {
|
|
$readonly_sentmail = false;
|
|
$save_sent_mail = $reload
|
|
? (bool)$this->vars->save_sent_mail
|
|
: true;
|
|
}
|
|
|
|
/* Initialize the IMP_Compose:: object. */
|
|
$imp_compose = $injector->getInstance('IMP_Factory_Compose')->create($this->vars->composeCache);
|
|
|
|
/* Init objects. */
|
|
$imp_imap = $injector->getInstance('IMP_Factory_Imap')->create();
|
|
$imp_ui = new IMP_Compose_Ui();
|
|
|
|
/* Determine the composition type - text or HTML.
|
|
$rtemode is null if browser does not support it. */
|
|
if ($session->get('imp', 'rteavail')) {
|
|
if ($prefs->isLocked('compose_html')) {
|
|
$rtemode = $prefs->getValue('compose_html');
|
|
} else {
|
|
$rtemode = $this->vars->rtemode;
|
|
if (is_null($rtemode)) {
|
|
$rtemode = $prefs->getValue('compose_html');
|
|
} else {
|
|
$rtemode = intval($rtemode);
|
|
$oldrtemode = intval($this->vars->oldrtemode);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Update the file attachment information. */
|
|
$attach_upload = $imp_compose->canUploadAttachment();
|
|
if ($attach_upload) {
|
|
/* Only notify if we are reloading the compose screen. */
|
|
$notify = !in_array($this->vars->actionID, array('send_message', 'save_draft'));
|
|
|
|
$deleteList = Horde_Util::getPost('delattachments', array());
|
|
|
|
/* Update the attachment information. */
|
|
foreach ($imp_compose as $key => $val) {
|
|
if (!in_array($key, $deleteList)) {
|
|
$val->getPart()->setDescription($this->vars->filter('file_description_' . $key));
|
|
$imp_compose[$key] = $val;
|
|
}
|
|
}
|
|
|
|
/* Delete attachments. */
|
|
foreach ($deleteList as $val) {
|
|
if ($notify) {
|
|
$notification->push(sprintf(_("Deleted attachment \"%s\"."), $imp_compose[$val]->getPart()->getName(true)), 'horde.success');
|
|
}
|
|
unset($imp_compose[$val]);
|
|
}
|
|
|
|
/* Add attachments. */
|
|
for ($i = 1, $fcount = count($_FILES); $i <= $fcount; ++$i) {
|
|
if (isset($_FILES['upload_' . $i]) &&
|
|
strlen($_FILES['upload_' . $i]['name'])) {
|
|
try {
|
|
$atc_ob = $imp_compose->addAttachmentFromUpload('upload_' . $i);
|
|
if ($atc_ob[0] instanceof IMP_Compose_Exception) {
|
|
throw $atc_ob[0];
|
|
}
|
|
if ($notify) {
|
|
$notification->push(sprintf(_("Added \"%s\" as an attachment."), $atc_ob[0]->getPart()->getName()), 'horde.success');
|
|
}
|
|
} catch (IMP_Compose_Exception $e) {
|
|
/* Any error will cancel the current action. */
|
|
$this->vars->actionID = null;
|
|
$notification->push($e, 'horde.error');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Get message priority. */
|
|
$priority = $this->vars->get('priority', 'normal');
|
|
|
|
/* Request read receipt? */
|
|
$request_read_receipt = (bool)$this->vars->request_read_receipt;
|
|
|
|
/* Run through the action handlers. */
|
|
$this->title = _("New Message");
|
|
switch ($this->vars->actionID) {
|
|
case 'mailto':
|
|
try {
|
|
$contents = $this->_getContents();
|
|
} catch (IMP_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
break;
|
|
}
|
|
|
|
$imp_headers = $contents->getHeader();
|
|
$header['to'] = '';
|
|
if ($this->vars->mailto) {
|
|
$header['to'] = $imp_headers->getValue('to');
|
|
}
|
|
if (empty($header['to'])) {
|
|
($header['to'] = strval($imp_headers->getOb('from'))) ||
|
|
($header['to'] = strval($imp_headers->getOb('reply-to')));
|
|
}
|
|
break;
|
|
|
|
case 'mailto_link':
|
|
$clink = new IMP_Compose_Link($this->vars);
|
|
if (isset($clink->args['body'])) {
|
|
$msg = $clink->args['body'];
|
|
}
|
|
foreach (array('to', 'cc', 'bcc', 'subject') as $val) {
|
|
if (isset($clink->args[$val])) {
|
|
$header[$val] = $clink->args[$val];
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'draft':
|
|
case 'editasnew':
|
|
case 'template':
|
|
case 'template_edit':
|
|
try {
|
|
switch ($this->vars->actionID) {
|
|
case 'draft':
|
|
$result = $imp_compose->resumeDraft($this->indices);
|
|
$resume = true;
|
|
break;
|
|
|
|
case 'editasnew':
|
|
$result = $imp_compose->editAsNew($this->indices);
|
|
break;
|
|
|
|
case 'template':
|
|
$result = $imp_compose->useTemplate($this->indices);
|
|
break;
|
|
|
|
case 'template_edit':
|
|
$result = $imp_compose->editTemplate($this->indices);
|
|
$this->vars->template_mode = true;
|
|
break;
|
|
}
|
|
|
|
if (!is_null($rtemode)) {
|
|
$rtemode = ($result['format'] == 'html');
|
|
}
|
|
$msg = $result['body'];
|
|
$header = array_merge(
|
|
$header,
|
|
$this->_convertToHeader($result)
|
|
);
|
|
if (!is_null($result['identity']) &&
|
|
($result['identity'] != $identity->getDefault()) &&
|
|
!$prefs->isLocked('default_identity')) {
|
|
$identity->setDefault($result['identity']);
|
|
$sent_mail = $identity->getValue(IMP_Mailbox::MBOX_SENT);
|
|
}
|
|
$priority = $result['priority'];
|
|
$request_read_receipt = $result['readreceipt'];
|
|
} catch (IMP_Compose_Exception $e) {
|
|
$notification->push($e);
|
|
}
|
|
break;
|
|
|
|
case 'reply':
|
|
case 'reply_all':
|
|
case 'reply_auto':
|
|
case 'reply_list':
|
|
try {
|
|
$contents = $this->_getContents();
|
|
} catch (IMP_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
break;
|
|
}
|
|
|
|
$reply_map = array(
|
|
'reply' => IMP_Compose::REPLY_SENDER,
|
|
'reply_all' => IMP_Compose::REPLY_ALL,
|
|
'reply_auto' => IMP_Compose::REPLY_AUTO,
|
|
'reply_list' => IMP_Compose::REPLY_LIST
|
|
);
|
|
|
|
$reply_msg = $imp_compose->replyMessage($reply_map[$this->vars->actionID], $contents, array(
|
|
'to' => $this->vars->to
|
|
));
|
|
$msg = $reply_msg['body'];
|
|
$header = $this->_convertToHeader($reply_msg);
|
|
$format = $reply_msg['format'];
|
|
|
|
switch ($reply_msg['type']) {
|
|
case IMP_Compose::REPLY_SENDER:
|
|
$this->vars->actionID = 'reply';
|
|
$this->title = _("Reply:");
|
|
break;
|
|
|
|
case IMP_Compose::REPLY_ALL:
|
|
if ($this->vars->actionID == 'reply_auto') {
|
|
$recip_list = $imp_compose->recipientList($header);
|
|
if (!empty($recip_list['list'])) {
|
|
$replyauto_all = count($recip_list['list']);
|
|
}
|
|
}
|
|
|
|
$this->vars->actionID = 'reply_all';
|
|
$this->title = _("Reply to All:");
|
|
break;
|
|
|
|
case IMP_Compose::REPLY_LIST:
|
|
if ($this->vars->actionID == 'reply_auto') {
|
|
$replyauto_list = true;
|
|
if (($parse_list = $injector->getInstance('Horde_ListHeaders')->parse('list-id', $contents->getHeader()->getValue('list-id'))) &&
|
|
!is_null($parse_list->label)) {
|
|
$replyauto_list_id = $parse_list->label;
|
|
}
|
|
}
|
|
|
|
$this->vars->actionID = 'reply_list';
|
|
$this->title = _("Reply to List:");
|
|
break;
|
|
}
|
|
|
|
if (!empty($reply_msg['lang'])) {
|
|
$reply_lang = array_values($reply_msg['lang']);
|
|
}
|
|
|
|
$this->title .= ' ' . $header['subject'];
|
|
|
|
if (!is_null($rtemode)) {
|
|
$rtemode = ($rtemode || ($format == 'html'));
|
|
}
|
|
break;
|
|
|
|
case 'replyall_revert':
|
|
case 'replylist_revert':
|
|
try {
|
|
$reply_msg = $imp_compose->replyMessage(
|
|
IMP_Compose::REPLY_SENDER,
|
|
$imp_compose->getContentsOb()
|
|
);
|
|
$header = $this->_convertToHeader($reply_msg);
|
|
} catch (IMP_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
}
|
|
break;
|
|
|
|
case 'forward_attach':
|
|
case 'forward_auto':
|
|
case 'forward_body':
|
|
case 'forward_both':
|
|
$fwd_map = array(
|
|
'forward_attach' => IMP_Compose::FORWARD_ATTACH,
|
|
'forward_auto' => IMP_Compose::FORWARD_AUTO,
|
|
'forward_body' => IMP_Compose::FORWARD_BODY,
|
|
'forward_both' => IMP_Compose::FORWARD_BOTH
|
|
);
|
|
|
|
try {
|
|
$fwd_msg = $imp_compose->forwardMessage(
|
|
$fwd_map[$this->vars->actionID],
|
|
$this->_getContents()
|
|
);
|
|
} catch (IMP_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
break;
|
|
}
|
|
|
|
$msg = $fwd_msg['body'];
|
|
$header = $this->_convertToHeader($fwd_msg);
|
|
$format = $fwd_msg['format'];
|
|
$rtemode = ($rtemode || (!is_null($rtemode) && ($format == 'html')));
|
|
$this->title = $fwd_msg['title'];
|
|
break;
|
|
|
|
case 'redirect_send':
|
|
try {
|
|
$num_msgs = $imp_compose->sendRedirectMessage($this->vars->to);
|
|
$imp_compose->destroy('send');
|
|
if ($isPopup) {
|
|
if ($prefs->getValue('compose_confirm')) {
|
|
$notification->push(ngettext("Message redirected successfully.", "Messages redirected successfully", count($num_msgs)), 'horde.success');
|
|
$this->_popupSuccess();
|
|
return;
|
|
}
|
|
echo Horde::wrapInlineScript(array('window.close();'));
|
|
} else {
|
|
$notification->push(ngettext("Message redirected successfully.", "Messages redirected successfully", count($num_msgs)), 'horde.success');
|
|
$this->_mailboxReturnUrl()->redirect();
|
|
}
|
|
exit;
|
|
} catch (Horde_Exception $e) {
|
|
$notification->push($e);
|
|
$this->vars->actionID = 'redirect_compose';
|
|
}
|
|
// Fall through.
|
|
|
|
case 'redirect_compose':
|
|
try {
|
|
$imp_compose->redirectMessage($this->indices);
|
|
$redirect = true;
|
|
$this->title = ngettext("Redirect", "Redirect Messages", count($this->indices));
|
|
} catch (IMP_Compose_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
}
|
|
break;
|
|
|
|
case 'auto_save_draft':
|
|
case 'save_draft':
|
|
case 'save_template':
|
|
case 'send_message':
|
|
// Drafts readonly is handled below.
|
|
if ($compose_disable &&
|
|
($this->vars->actionID == 'send_message')) {
|
|
break;
|
|
}
|
|
|
|
try {
|
|
$header['from'] = strval($identity->getFromLine(null, $this->vars->from));
|
|
} catch (Horde_Exception $e) {
|
|
$header['from'] = '';
|
|
$notification->push($e);
|
|
break;
|
|
}
|
|
|
|
$header['to'] = $this->vars->to;
|
|
$header['cc'] = $this->vars->cc;
|
|
$header['bcc'] = $this->vars->bcc;
|
|
|
|
$header['subject'] = strval($this->vars->subject);
|
|
$message = strval($this->vars->message);
|
|
|
|
/* Save the draft. */
|
|
switch ($this->vars->actionID) {
|
|
case 'auto_save_draft':
|
|
case 'save_draft':
|
|
case 'save_template':
|
|
if (!$readonly_drafts ||
|
|
($this->vars->actionID == 'save_template')) {
|
|
$save_opts = array(
|
|
'html' => $rtemode,
|
|
'priority' => $priority,
|
|
'readreceipt' => $request_read_receipt
|
|
);
|
|
|
|
try {
|
|
switch ($this->vars->actionID) {
|
|
case 'save_template':
|
|
$result = $imp_compose->saveTemplate($header, $message, $save_opts);
|
|
break;
|
|
|
|
default:
|
|
$result = $imp_compose->saveDraft($header, $message, $save_opts);
|
|
break;
|
|
}
|
|
|
|
/* Closing draft if requested by preferences. */
|
|
switch ($this->vars->actionID) {
|
|
case 'save_draft':
|
|
if ($isPopup) {
|
|
if ($prefs->getValue('close_draft')) {
|
|
$imp_compose->destroy('save_draft');
|
|
echo Horde::wrapInlineScript(array('window.close();'));
|
|
exit;
|
|
}
|
|
$notification->push($result, 'horde.success');
|
|
} else {
|
|
$notification->push($result, 'horde.success');
|
|
if ($prefs->getValue('close_draft')) {
|
|
$imp_compose->destroy('save_draft');
|
|
$this->_mailboxReturnUrl()->redirect();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'save_template':
|
|
if ($isPopup) {
|
|
echo Horde::wrapInlineScript(array('window.close();'));
|
|
exit;
|
|
}
|
|
|
|
$notification->push($result, 'horde.success');
|
|
$this->_mailboxReturnUrl()->redirect();
|
|
break;
|
|
}
|
|
} catch (IMP_Compose_Exception $e) {
|
|
if ($this->vars->actionID == 'save_draft') {
|
|
$notification->push($e);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->vars->actionID == 'auto_save_draft') {
|
|
$r = new stdClass;
|
|
$r->requestToken = $session->getToken();
|
|
$r->formToken = $session->getNonce();
|
|
|
|
$response = new Horde_Core_Ajax_Response_HordeCore($r);
|
|
$response->sendAndExit();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
$header['replyto'] = $identity->getValue('replyto_addr');
|
|
|
|
if ($this->vars->sent_mail) {
|
|
$sent_mail = IMP_Mailbox::formFrom($this->vars->sent_mail);
|
|
}
|
|
|
|
try {
|
|
$imp_compose->buildAndSendMessage(
|
|
$message,
|
|
$header,
|
|
$identity,
|
|
array(
|
|
'encrypt' => $prefs->isLocked('default_encrypt') ? $prefs->getValue('default_encrypt') : $this->vars->encrypt_options,
|
|
'html' => $rtemode,
|
|
'pgp_attach_pubkey' => $this->vars->pgp_attach_pubkey,
|
|
'priority' => $priority,
|
|
'save_sent' => $save_sent_mail,
|
|
'sent_mail' => $sent_mail,
|
|
'signature' => $this->vars->signature,
|
|
'strip_attachments' => !$this->vars->save_attachments_select,
|
|
'readreceipt' => $request_read_receipt,
|
|
'vcard_attach' => $this->vars->vcard ? $identity->getValue('fullname') : null
|
|
)
|
|
);
|
|
$imp_compose->destroy('send');
|
|
|
|
if ($isPopup) {
|
|
if ($prefs->getValue('compose_confirm')) {
|
|
$notification->push(_("Message sent successfully."), 'horde.success');
|
|
$this->_popupSuccess();
|
|
return;
|
|
}
|
|
echo Horde::wrapInlineScript(array('window.close();'));
|
|
} else {
|
|
$notification->push(_("Message sent successfully."), 'horde.success');
|
|
$this->_mailboxReturnUrl()->redirect();
|
|
}
|
|
exit;
|
|
} catch (IMP_Compose_Exception $e) {
|
|
$code = $e->getCode();
|
|
$notification->push($e->getMessage(), strpos($code, 'horde.') === 0 ? $code : 'horde.error');
|
|
|
|
/* Switch to tied identity. */
|
|
if (!is_null($e->tied_identity)) {
|
|
$identity->setDefault($e->tied_identity);
|
|
$notification->push(_("Your identity has been switched to the identity associated with the current recipient address. The identity will not be checked again during this compose action."));
|
|
}
|
|
|
|
switch ($e->encrypt) {
|
|
case 'pgp_symmetric_passphrase_dialog':
|
|
$imp_ui->passphraseDialog('pgp_symm', $imp_compose->getCacheId());
|
|
break;
|
|
|
|
case 'pgp_passphrase_dialog':
|
|
$imp_ui->passphraseDialog('pgp');
|
|
break;
|
|
|
|
case 'smime_passphrase_dialog':
|
|
$imp_ui->passphraseDialog('smime');
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 'fwd_digest':
|
|
if (count($this->indices)) {
|
|
try {
|
|
$res = $imp_compose->forwardMultipleMessages($this->indices);
|
|
$header['subject'] = $res['subject'];
|
|
$fwd_msg = array('type' => IMP_Compose::FORWARD_ATTACH);
|
|
} catch (IMP_Compose_Exception $e) {
|
|
$notification->push($e, 'horde.error');
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'cancel_compose':
|
|
case 'discard_compose':
|
|
$imp_compose->destroy($this->vars->actionID == 'cancel_compose' ? 'cancel' : 'discard');
|
|
if ($isPopup) {
|
|
echo Horde::wrapInlineScript(array('window.close();'));
|
|
} else {
|
|
$this->_mailboxReturnUrl()->redirect();
|
|
}
|
|
exit;
|
|
|
|
case 'template_new':
|
|
$this->vars->template_mode = true;
|
|
break;
|
|
}
|
|
|
|
/* Get the message cache ID. */
|
|
$composeCacheID = filter_var($imp_compose->getCacheId(), FILTER_SANITIZE_STRING);
|
|
|
|
/* Attach autocompleters to the compose form elements. */
|
|
if ($redirect) {
|
|
$imp_ui->attachAutoCompleter(array('to'));
|
|
} else {
|
|
$imp_ui->attachAutoCompleter(array('to', 'cc', 'bcc'));
|
|
$spellcheck = $imp_ui->attachSpellChecker();
|
|
$page_output->addScriptFile('ieescguard.js', 'horde');
|
|
}
|
|
|
|
$max_attach = $imp_compose->additionalAttachmentsAllowed();
|
|
|
|
/* Get the URL to use for the cancel action. If the attachments cache
|
|
* is not empty, or this is the resume drafts page, we must reload
|
|
* this page and delete the attachments and/or the draft message. */
|
|
if ($isPopup) {
|
|
if ($resume || count($imp_compose)) {
|
|
$cancel_url = self::url()->setRaw(true)->add(array(
|
|
'actionID' => 'cancel_compose',
|
|
'compose_requestToken' => $session->getToken(),
|
|
'composeCache' => $composeCacheID,
|
|
'popup' => 1
|
|
));
|
|
$discard_url = clone $cancel_url;
|
|
$discard_url->add('actionID', 'discard_compose');
|
|
} else {
|
|
$cancel_url = $discard_url = '';
|
|
}
|
|
} elseif ($resume || count($imp_compose)) {
|
|
$cancel_url = $this->_mailboxReturnUrl(self::url()->setRaw(true))->setRaw(true)->add(array(
|
|
'actionID' => 'cancel_compose',
|
|
'compose_requestToken' => $session->getToken(),
|
|
'composeCache' => $composeCacheID
|
|
));
|
|
$discard_url = clone $cancel_url;
|
|
$discard_url->add('actionID', 'discard_compose');
|
|
} else {
|
|
$cancel_url = $discard_url = $this->_mailboxReturnUrl(false)->setRaw(true);
|
|
}
|
|
|
|
/* Grab any data that we were supplied with. */
|
|
if (!strlen($msg)) {
|
|
$msg = $this->vars->get('message', strval($this->vars->body));
|
|
if ($browser->hasQuirk('double_linebreak_textarea')) {
|
|
$msg = preg_replace('/(\r?\n){3}/', '$1', $msg);
|
|
}
|
|
$msg = "\n" . $msg;
|
|
}
|
|
if (isset($this->vars->signature)) {
|
|
$signature = $this->vars->signature;
|
|
if ($browser->hasQuirk('double_linebreak_textarea')) {
|
|
$signature = preg_replace('/(\r?\n){3}/', '$1', $signature);
|
|
}
|
|
$signatureChanged = $signature != $identity->getSignature($oldrtemode ? 'html' : 'text');
|
|
} else {
|
|
$signatureChanged = false;
|
|
}
|
|
|
|
/* Convert from Text -> HTML or vice versa if RTE mode changed. */
|
|
if (!is_null($oldrtemode) && ($oldrtemode != $rtemode)) {
|
|
$msg = $imp_ui->convertComposeText($msg, $rtemode ? 'html' : 'text');
|
|
if ($signatureChanged) {
|
|
$signature = $imp_ui->convertComposeText($signature, $rtemode ? 'html' : 'text');
|
|
}
|
|
}
|
|
|
|
/* If this is the first page load for this compose item, add auto BCC
|
|
* addresses. */
|
|
if (!$reload && !$resume) {
|
|
$header['bcc'] = strval($identity->getBccAddresses());
|
|
}
|
|
|
|
foreach (array('to', 'cc', 'bcc') as $val) {
|
|
if (!isset($header[$val])) {
|
|
$header[$val] = $this->vars->$val;
|
|
}
|
|
}
|
|
|
|
if (!isset($header['subject'])) {
|
|
$header['subject'] = $this->vars->subject;
|
|
}
|
|
|
|
/* If PGP encryption is set by default, and we have a recipient list
|
|
* on first load, make sure we have public keys for all recipients. */
|
|
$encrypt_options = $prefs->isLocked('default_encrypt')
|
|
? $prefs->getValue('default_encrypt')
|
|
: $this->vars->encrypt_options;
|
|
if ($prefs->getValue('use_pgp') &&
|
|
!$prefs->isLocked('default_encrypt') &&
|
|
$prefs->getValue('pgp_reply_pubkey')) {
|
|
$default_encrypt = $prefs->getValue('default_encrypt');
|
|
if (!$reload &&
|
|
in_array($default_encrypt, array(IMP_Crypt_Pgp::ENCRYPT, IMP_Crypt_Pgp::SIGNENC))) {
|
|
$addrs = $imp_compose->recipientList($header);
|
|
if (!empty($addrs['list'])) {
|
|
$imp_pgp = $injector->getInstance('IMP_Crypt_Pgp');
|
|
try {
|
|
foreach ($addrs['list'] as $val) {
|
|
$imp_pgp->getPublicKey(strval($val));
|
|
}
|
|
} catch (Horde_Exception $e) {
|
|
$notification->push(_("PGP encryption cannot be used by default as public keys cannot be found for all recipients."), 'horde.warning');
|
|
$encrypt_options = ($default_encrypt == IMP_Crypt_Pgp::ENCRYPT) ? IMP::ENCRYPT_NONE : IMP_Crypt_Pgp::SIGN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Define some variables used in the javascript code. */
|
|
$js_vars = array(
|
|
'ImpComposeBase.editor_on' => $rtemode,
|
|
'ImpCompose.auto_save' => intval($prefs->getValue('auto_save_drafts')),
|
|
'ImpCompose.cancel_url' => strval($cancel_url),
|
|
'ImpCompose.cursor_pos' => ($rtemode ? null : $prefs->getValue('compose_cursor')),
|
|
'ImpCompose.discard_url' => strval($discard_url),
|
|
'ImpCompose.max_attachments' => (($max_attach === true) ? null : $max_attach),
|
|
'ImpCompose.popup' => intval($isPopup),
|
|
'ImpCompose.redirect' => intval($redirect),
|
|
'ImpCompose.reloaded' => intval($reload),
|
|
'ImpCompose.sm_check' => intval(!$prefs->isLocked(IMP_Mailbox::MBOX_SENT)),
|
|
'ImpCompose.spellcheck' => intval($spellcheck && $prefs->getValue('compose_spellcheck')),
|
|
'ImpCompose.text' => array(
|
|
'cancel' => _("Cancelling this message will permanently discard its contents.") . "\n" . _("Are you sure you want to do this?"),
|
|
'change_identity' => _("You have edited your signature. Change the identity and lose your changes?"),
|
|
'discard' => _("Doing so will discard this message permanently."),
|
|
'file' => _("File"),
|
|
'nosubject' => _("The message does not have a Subject entered.") . "\n" . _("Send message without a Subject?"),
|
|
'recipient' => _("You must specify a recipient.")
|
|
)
|
|
);
|
|
|
|
/* Set up the base view now. */
|
|
$view = $injector->createInstance('Horde_View');
|
|
$view->addHelper('FormTag');
|
|
$view->addHelper('Horde_Core_View_Helper_Accesskey');
|
|
$view->addHelper('Horde_Core_View_Helper_Help');
|
|
$view->addHelper('Horde_Core_View_Helper_Image');
|
|
$view->addHelper('Horde_Core_View_Helper_Label');
|
|
$view->addHelper('Tag');
|
|
|
|
$view->allow_compose = !$compose_disable;
|
|
$view->post_action = self::url();
|
|
|
|
$blank_url = new Horde_Url('#');
|
|
|
|
if ($redirect) {
|
|
/* Prepare the redirect template. */
|
|
$view->cacheid = $composeCacheID;
|
|
$view->title = $this->title;
|
|
$view->token = $session->getToken();
|
|
|
|
if ($registry->hasMethod('contacts/search')) {
|
|
$view->abook = $blank_url->copy()->link(array(
|
|
'class' => 'widget',
|
|
'id' => 'redirect_abook',
|
|
'title' => _("Address Book")
|
|
));
|
|
$js_vars['ImpCompose.redirect_contacts'] = strval(IMP_Basic_Contacts::url()->add(array('to_only' => 1))->setRaw(true));
|
|
}
|
|
|
|
$view->input_value = $header['to'];
|
|
|
|
$this->output = $view->render('basic/compose/redirect');
|
|
} else {
|
|
/* Prepare the compose template. */
|
|
$view->file_upload = $attach_upload;
|
|
|
|
$hidden = array(
|
|
'actionID' => '',
|
|
'attachmentAction' => '',
|
|
'compose_formToken' => $session->getNonce(),
|
|
'compose_requestToken' => $session->getToken(),
|
|
'composeCache' => $composeCacheID,
|
|
'composeHmac' => $imp_compose->getHmac(),
|
|
'oldrtemode' => $rtemode,
|
|
'rtemode' => $rtemode,
|
|
'user' => $registry->getAuth()
|
|
);
|
|
|
|
if ($attach_upload) {
|
|
$hidden['MAX_FILE_SIZE'] = $session->get('imp', 'file_upload');
|
|
}
|
|
foreach (array('page', 'start', 'popup', 'template_mode') as $val) {
|
|
$hidden[$val] = $this->vars->$val;
|
|
}
|
|
|
|
$view->hidden = $hidden;
|
|
$view->tabindex = 1;
|
|
$view->title = $this->title;
|
|
|
|
if (!$this->vars->template_mode) {
|
|
$view->send_msg = true;
|
|
$view->save_draft = ($imp_imap->access(IMP_Imap::ACCESS_DRAFTS) && !$readonly_drafts);
|
|
}
|
|
|
|
$view->resume = $resume;
|
|
|
|
$view->di_locked = $prefs->isLocked('default_identity');
|
|
if ($view->di_locked) {
|
|
$view->fromaddr_locked = $prefs->isLocked('from_addr');
|
|
try {
|
|
$view->from = $identity->getFromLine(null, $this->vars->from);
|
|
} catch (Horde_Exception $e) {}
|
|
} else {
|
|
$select_list = $identity->getSelectList();
|
|
$view->last_identity = $identity->getDefault();
|
|
|
|
if (count($select_list) > 1) {
|
|
$view->count_select_list = true;
|
|
$t_select_list = array();
|
|
foreach ($select_list as $key => $select) {
|
|
$t_select_list[] = array(
|
|
'label' => $select,
|
|
'selected' => ($key == $identity->getDefault()),
|
|
'value' => $key
|
|
);
|
|
}
|
|
$view->select_list = $t_select_list;
|
|
} else {
|
|
$view->identity_default = $identity->getDefault();
|
|
$view->identity_text = $select_list[0];
|
|
}
|
|
}
|
|
$view->signature = $identity->hasSignature(true);
|
|
|
|
$addr_array = array(
|
|
'to' => _("_To"),
|
|
'cc' => _("_Cc"),
|
|
'bcc' => _("_Bcc")
|
|
);
|
|
|
|
$address_array = array();
|
|
foreach ($addr_array as $val => $label) {
|
|
$address_array[] = array(
|
|
'id' => $val,
|
|
'label' => $label,
|
|
'val' => $header[$val]
|
|
);
|
|
}
|
|
$view->addr = $address_array;
|
|
|
|
$view->subject = $header['subject'];
|
|
|
|
if ($prefs->getValue('set_priority')) {
|
|
$view->set_priority = true;
|
|
|
|
$priorities = array(
|
|
'high' => _("High"),
|
|
'normal' => _("Normal"),
|
|
'low' => _("Low")
|
|
);
|
|
|
|
$priority_option = array();
|
|
foreach ($priorities as $key => $val) {
|
|
$priority_option[] = array(
|
|
'label' => $val,
|
|
'selected' => ($priority == $key),
|
|
'val' => $key
|
|
);
|
|
}
|
|
$view->pri_opt = $priority_option;
|
|
}
|
|
|
|
$compose_options = array();
|
|
|
|
if ($registry->hasMethod('contacts/search')) {
|
|
$compose_options[] = array(
|
|
'url' => $blank_url->copy()->link(array(
|
|
'class' => 'widget',
|
|
'id' => 'addressbook_popup'
|
|
)),
|
|
'img' => Horde_Themes_Image::tag('addressbook_browse.png'),
|
|
'label' => _("Address Book")
|
|
);
|
|
$js_vars['ImpCompose.contacts_url'] = strval(IMP_Basic_Contacts::url()->setRaw(true));
|
|
}
|
|
if ($spellcheck) {
|
|
$compose_options[] = array(
|
|
'url' => $blank_url->copy()->link(array(
|
|
'class' => 'widget',
|
|
'id' => 'spellcheck'
|
|
)),
|
|
'img' => '',
|
|
'label' => ''
|
|
);
|
|
}
|
|
if ($attach_upload) {
|
|
$url = new Horde_Url('#attachments');
|
|
$compose_options[] = array(
|
|
'url' => $url->link(array('class' => 'widget')),
|
|
'img' => Horde_Themes_Image::tag('attachment.png'),
|
|
'label' => _("Attachments")
|
|
);
|
|
}
|
|
$view->compose_options = $compose_options;
|
|
|
|
if ($imp_imap->access(IMP_Imap::ACCESS_FOLDERS) &&
|
|
!$prefs->isLocked('save_sent_mail')) {
|
|
$view->ssm = true;
|
|
if ($readonly_sentmail) {
|
|
$notification->push(sprintf(_("Cannot save sent-mail message to \"%s\" as that mailbox is read-only.", $sent_mail->display), 'horde.warning'));
|
|
}
|
|
$view->ssm_selected = $reload
|
|
? $save_sent_mail
|
|
: ($sent_mail && $identity->saveSentmail());
|
|
if ($this->vars->sent_mail) {
|
|
$sent_mail = IMP_Mailbox::formFrom($this->vars->sent_mail);
|
|
}
|
|
if (!$prefs->isLocked(IMP_Mailbox::MBOX_SENT)) {
|
|
$iterator = new IMP_Ftree_IteratorFilter(
|
|
$injector->getInstance('IMP_Ftree')
|
|
);
|
|
$iterator->add($iterator::NONIMAP);
|
|
$iterator->mboxes = array('INBOX');
|
|
|
|
$ssm_options = array(
|
|
'abbrev' => false,
|
|
'iterator' => $iterator,
|
|
'selected' => $sent_mail
|
|
);
|
|
|
|
/* Check to make sure the sent-mail mailbox is created -
|
|
* it needs to exist to show up in drop-down list. */
|
|
if ($sent_mail) {
|
|
$sent_mail->create();
|
|
}
|
|
|
|
$view->ssm_mboxes = new IMP_Ftree_Select($ssm_options);
|
|
} else {
|
|
if ($sent_mail) {
|
|
$sent_mail = '"' . $sent_mail->display_html . '"';
|
|
}
|
|
$view->ssm_mbox = $sent_mail;
|
|
}
|
|
}
|
|
|
|
$view->rrr_selected = $prefs->isLocked('request_mdn')
|
|
? null
|
|
: (($prefs->getValue('request_mdn') == 'always') || $request_read_receipt);
|
|
|
|
if (!is_null($rtemode) && !$prefs->isLocked('compose_html')) {
|
|
$view->compose_html = true;
|
|
$view->html_switch = $blank_url->copy()->link(array(
|
|
'id' => 'rte_toggle',
|
|
'title' => _("Switch Composition Method")
|
|
));
|
|
$view->rtemode = $rtemode;
|
|
}
|
|
|
|
if (isset($replyauto_all)) {
|
|
$view->replyauto_all = $replyauto_all;
|
|
} elseif (isset($replyauto_list)) {
|
|
$view->replyauto_list = true;
|
|
if (isset($replyauto_list_id)) {
|
|
$view->replyauto_list_id = $replyauto_list_id;
|
|
}
|
|
}
|
|
|
|
if (isset($reply_lang)) {
|
|
$view->reply_lang = implode(',', $reply_lang);
|
|
}
|
|
|
|
$view->message = $msg;
|
|
if ($signatureChanged) {
|
|
$view->signatureContent = $signature;
|
|
}
|
|
|
|
if ($prefs->getValue('use_pgp') || $prefs->getValue('use_smime')) {
|
|
if ($prefs->isLocked('default_encrypt')) {
|
|
$view->use_encrypt = false;
|
|
} else {
|
|
$view->use_encrypt = true;
|
|
$view->encrypt_options = $imp_ui->encryptList($encrypt_options);
|
|
}
|
|
|
|
if ($prefs->getValue('use_pgp') && $prefs->getValue('pgp_public_key')) {
|
|
$view->pgp_options = true;
|
|
$view->pgp_attach_pubkey = $reload
|
|
? $this->vars->pgp_attach_pubkey
|
|
: $prefs->getValue('pgp_attach_pubkey');
|
|
}
|
|
}
|
|
|
|
if ($registry->hasMethod('contacts/ownVCard')) {
|
|
$view->vcard = true;
|
|
$view->attach_vcard = $this->vars->vcard;
|
|
}
|
|
|
|
if ($attach_upload) {
|
|
$view->attach_size = IMP::numberFormat($imp_compose->maxAttachmentSize(), 0);
|
|
$view->maxattachmentnumber = !$max_attach;
|
|
|
|
$save_attach = $prefs->getValue('save_attachments');
|
|
|
|
if ($view->ssm && !$prefs->isLocked('save_attachments')) {
|
|
$view->show_link_save_attach = true;
|
|
$view->attach_options = array(array(
|
|
'label' => _("Save attachments with message in sent-mail mailbox?"),
|
|
'name' => 'save_attachments_select',
|
|
'val' => ($reload ? $this->vars->save_attachments_select : ($save_attach == 'always'))
|
|
));
|
|
}
|
|
|
|
if (count($imp_compose)) {
|
|
$view->numberattach = true;
|
|
|
|
$atc = array();
|
|
$v = $injector->getInstance('IMP_Factory_MimeViewer');
|
|
foreach ($imp_compose as $data) {
|
|
$mime = $data->getPart();
|
|
$type = $mime->getType();
|
|
|
|
$entry = array(
|
|
'name' => $mime->getName(true),
|
|
'icon' => $v->getIcon($type),
|
|
'number' => $data->id,
|
|
'type' => $type,
|
|
'size' => $mime->getSize(),
|
|
'description' => $mime->getDescription(true)
|
|
);
|
|
|
|
if (!(isset($fwd_msg) &&
|
|
($fwd_msg['type'] != IMP_Compose::FORWARD_BODY)) &&
|
|
($type != 'application/octet-stream')) {
|
|
$entry['name'] = $data->viewUrl()->link(array(
|
|
'class' => 'link',
|
|
'target' => 'compose_preview_window',
|
|
'title' => _("Preview")
|
|
)) . htmlspecialchars($entry['name']) . '</a>';
|
|
}
|
|
|
|
$atc[] = $entry;
|
|
}
|
|
$view->atc = $atc;
|
|
}
|
|
}
|
|
|
|
$this->output = $view->render('basic/compose/compose');
|
|
}
|
|
|
|
$page_output->addScriptPackage('IMP_Script_Package_ComposeBase');
|
|
$page_output->addScriptFile('compose.js');
|
|
$page_output->addScriptFile('editor.js');
|
|
$page_output->addScriptFile('imp.js');
|
|
$page_output->addInlineJsVars($js_vars);
|
|
if (!$redirect) {
|
|
$imp_ui->addIdentityJs();
|
|
}
|
|
|
|
if ($rtemode && !$redirect) {
|
|
$page_output->addScriptPackage('IMP_Script_Package_Editor');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array $opts
|
|
* - full: (boolean) If true, output full URL.
|
|
*/
|
|
static public function url(array $opts = array())
|
|
{
|
|
return Horde::url('basic.php', !empty($opts['full']))->add('page', 'compose')->unique();
|
|
}
|
|
|
|
/**
|
|
* Create the IMP_Contents objects needed to create a message.
|
|
*
|
|
* @return IMP_Contents The IMP_Contents object.
|
|
* @throws IMP_Exception
|
|
*/
|
|
protected function _getContents()
|
|
{
|
|
$ob = null;
|
|
|
|
if (count($this->indices)) {
|
|
try {
|
|
$ob = $GLOBALS['injector']->getInstance('IMP_Factory_Contents')->create($this->indices);
|
|
} catch (Horde_Exception $e) {}
|
|
}
|
|
|
|
if (!is_null($ob)) {
|
|
return $ob;
|
|
}
|
|
|
|
$this->vars->buid = null;
|
|
$this->vars->type = 'new';
|
|
throw new IMP_Exception(_("Could not retrieve message data from the mail server."));
|
|
}
|
|
|
|
/**
|
|
* Generate mailbox return URL.
|
|
*
|
|
* @param string $url The URL to use instead of the default.
|
|
*
|
|
* @return string The mailbox return URL.
|
|
*/
|
|
protected function _mailboxReturnUrl($url = null)
|
|
{
|
|
$url = $this->indices->mailbox->url('mailbox');
|
|
|
|
foreach (array('start', 'page') as $key) {
|
|
if (isset($vars->$key)) {
|
|
$url->add($key, $vars->$key);
|
|
}
|
|
}
|
|
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* Generate a popup success window.
|
|
*/
|
|
protected function _popupSuccess()
|
|
{
|
|
global $page_output;
|
|
|
|
$page_output->topbar = $page_output->sidebar = false;
|
|
$page_output->addInlineScript(array(
|
|
'$("close_success").observe("click", function() { window.close(); })'
|
|
), true);
|
|
|
|
$this->title =_("Message Successfully Sent");
|
|
|
|
$view = new Horde_View(array(
|
|
'templatePath' => IMP_TEMPLATES . '/basic/compose'
|
|
));
|
|
|
|
$view->close = Horde::widget(array(
|
|
'id' => 'close_success',
|
|
'url' => new Horde_Url('#'),
|
|
'title' => _("Close this window")
|
|
));
|
|
$view->new = Horde::widget(array(
|
|
'url' => self::url(),
|
|
'title' => _("New Message")
|
|
));
|
|
|
|
$this->output = $view->render('success');
|
|
}
|
|
|
|
/**
|
|
* Convert a compose response object to header values.
|
|
*
|
|
* @param array $in Compose response object.
|
|
*
|
|
* @return array Header entry.
|
|
*/
|
|
protected function _convertToHeader($in)
|
|
{
|
|
$out = array();
|
|
|
|
if (isset($in['addr'])) {
|
|
$out['to'] = strval($in['addr']['to']);
|
|
$out['cc'] = strval($in['addr']['cc']);
|
|
$out['bcc'] = strval($in['addr']['bcc']);
|
|
}
|
|
|
|
if (isset($in['subject'])) {
|
|
$out['subject'] = $in['subject'];
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
}
|