/** */ public function display(Horde_Core_Prefs_Ui $ui) { global $injector, $page_output, $prefs; $page_output->addScriptFile('prefs/folder.js'); $page_output->addInlineJsVars(array('ImpFolderPrefs.mboxes.trash' => _("Enter the name for your new trash mailbox."))); $imp_search = $injector->getInstance('IMP_Search'); $trash = IMP_Mailbox::getPref(IMP_Mailbox::MBOX_TRASH); $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/prefs')); $view->addHelper('FormTag'); $view->addHelper('Horde_Core_View_Helper_Label'); $view->addHelper('Tag'); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add(array($iterator::NONIMAP, $iterator::REMOTE)); $iterator->mboxes = array('INBOX'); $view->flist = new IMP_Ftree_Select(array('iterator' => $iterator, 'new_mbox' => true, 'selected' => $trash)); $view->nombox = IMP_Mailbox::formTo(self::PREF_NO_MBOX); $view->special_use = $this->_getSpecialUse(Horde_Imap_Client::SPECIALUSE_TRASH); if (!$prefs->isLocked('vfolder') || $imp_search['vtrash']->enabled) { $view->vtrash = IMP_Mailbox::formTo($imp_search->createSearchId('vtrash')); if ($trash) { $view->vtrash_select = $trash->vtrash; } } return $view->render('trash'); }
/** * Purge the old sent-mail mailboxes. * * @return boolean Whether any mailboxes were deleted. */ public function execute() { global $injector, $notification, $prefs; $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add($iterator::CONTAINERS); $mbox_list = array(); /* Get list of all mailboxes, parse through and get the list of all * old sent-mail mailboxes. Then sort this array according to the * date. */ $sent_mail = $injector->getInstance('IMP_Identity')->getAllSentmail(); foreach (array_map('strval', $iterator) as $k) { foreach ($sent_mail as $mbox) { if (preg_match('/^' . preg_quote($mbox, '/') . '-([^-]+)-([0-9]{4})$/i', $k, $regs)) { $mbox_list[$k] = is_numeric($regs[1]) ? mktime(0, 0, 0, $regs[1], 1, $regs[2]) : strtotime("{$regs['1']} 1, {$regs['2']}"); } } } arsort($mbox_list, SORT_NUMERIC); $return_val = false; /* See if any mailboxes need to be purged. */ $purge = array_slice(array_keys($mbox_list), $prefs->getValue('delete_sentmail_monthly_keep')); if (count($purge)) { $notification->push(_("Old sent-mail mailboxes being purged."), 'horde.message'); /* Delete the old mailboxes now. */ foreach (IMP_Mailbox::get($purge) as $val) { if ($val->delete()) { $return_val = true; } } } return $return_val; }
/** * Get object properties. * Only create mailbox list on demand. * * @see __get() */ public function __get($name) { global $injector; switch ($name) { case 'mboxes': $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add(array($iterator::CONTAINERS, $iterator::NONIMAP)); return array_map('strval', iterator_to_array($iterator, false)); } return parent::__get($name); }
/** * AJAX action: Login to a remote account. * * Variables used: * - password: (string) Remote server password. * - password_base64: (boolean) If true, password is base64 encoded. * - password_save: (boolean) If true, password is saved (encrypted) * to config data. * - remoteid: (string) Remote server ID (base64url encoded). * - unsub: (boolean) If true, show unsubscribed mailboxes. * * @return boolean An object with the following properties: * - success: (boolean) True if login was successful. */ public function remoteLogin() { global $injector, $notification, $prefs; $remote = $injector->getInstance('IMP_Remote'); $remoteid = IMP_Mailbox::formFrom($this->vars->remoteid); $res = new stdClass(); $res->success = false; if (!isset($remote[$remoteid])) { $notification->push(_("Could not find remote server configuration."), 'horde.error'); return $res; } $password = $this->vars->password; if ($this->vars->password_base64) { $password = base64_decode($password); } $remote_ob = $remote[$remoteid]; try { switch ($remote_ob->login($password, $this->vars->password_save)) { case $remote_ob::LOGIN_BAD_CHANGED: $remote[$remoteid] = $remote_ob; // Fall-through // Fall-through case $remote_ob::LOGIN_BAD: throw new Exception(); case $remote_ob::LOGIN_OK_CHANGED: $remote[$remoteid] = $remote_ob; break; } $res->success = true; $notification->push(sprintf(_("Successfully authenticated to %s."), $remote_ob->label), 'horde.success'); $ftree = $injector->getInstance('IMP_Ftree'); $ftree->delete($remote_ob); $ftree->insert($remote_ob); $ftree[$remote_ob]->open = true; $this->_base->queue->setMailboxOpt('expand', 1); $iterator = new IMP_Ftree_IteratorFilter(new IMP_Ftree_Iterator($ftree[$remote_ob])); if ($this->vars->unsub) { $ftree->loadUnsubscribed(); $iterator->remove($iterator::UNSUB); } switch ($prefs->getValue('nav_expanded')) { case IMP_Ftree_Prefs_Expanded::NO: $iterator->add($iterator::CHILDREN); break; case IMP_Ftree_Prefs_Expanded::LAST: $iterator->add($iterator::EXPANDED); break; } array_map(array($ftree->eltdiff, 'add'), iterator_to_array($iterator, false)); } catch (Exception $e) { $notification->push(sprintf(_("Could not authenticate to %s."), $remote_ob->label), 'horde.error'); } return $res; }
/** * Returns the list of mailboxes to poll. * * @param boolean $sort Sort the directory list? * * @return array The list of mailboxes to poll (IMP_Mailbox objects). */ public function getPollList($sort = false) { global $injector; $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add(array($iterator::CONTAINERS, $iterator::NONIMAP)); if ($this->_data !== true) { $iterator->add($iterator::POLLED); } $plist = array_map('strval', iterator_to_array($iterator, false)); if ($sort) { $this->_ftree->sortList($plist, $this->_ftree[IMP_Ftree::BASE_ELT]); } return IMP_Mailbox::get($plist); }
/** */ public function accept() { $curr = $this->current(); if (!$curr->nonimap) { return true; } if (($curr->remote || $curr->namespace) && $curr->children) { $iterator = new IMP_Ftree_IteratorFilter(new IMP_Ftree_Iterator($curr)); $iterator->add(array($iterator::CONTAINERS, $iterator::NONIMAP)); foreach ($iterator as $val) { return true; } } return false; }
/** */ public function display(Horde_Core_Prefs_Ui $ui) { global $injector, $page_output; $page_output->addScriptFile('prefs/folder.js'); $page_output->addInlineJsVars(array('ImpFolderPrefs.mboxes.drafts' => _("Enter the name for your new drafts mailbox."))); $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/prefs')); $view->addHelper('Horde_Core_View_Helper_Label'); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add(array($iterator::NONIMAP, $iterator::REMOTE)); $iterator->mboxes = array('INBOX'); $view->flist = new IMP_Ftree_Select(array('basename' => true, 'iterator' => $iterator, 'new_mbox' => true, 'selected' => IMP_Mailbox::getPref(IMP_Mailbox::MBOX_DRAFTS))); $view->nombox = IMP_Mailbox::formTo(self::PREF_NO_MBOX); $view->special_use = $this->_getSpecialUse(Horde_Imap_Client::SPECIALUSE_DRAFTS); return $view->render('drafts'); }
/** */ public function display(Horde_Core_Prefs_Ui $ui) { global $injector, $page_output, $prefs; if ($prefs->isLocked(IMP_Mailbox::MBOX_TEMPLATES)) { return ''; } $page_output->addScriptFile('prefs/folder.js'); $page_output->addInlineJsVars(array('ImpFolderPrefs.mboxes.templates' => _("Enter the name for your new compose templates mailbox."))); $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/prefs')); $view->addHelper('Horde_Core_View_Helper_Label'); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add(array($iterator::NONIMAP, $iterator::REMOTE)); $iterator->mboxes = array('INBOX'); $view->mbox_flist = new IMP_Ftree_Select(array('iterator' => $iterator, 'new_mbox' => true, 'selected' => IMP_Mailbox::getPref(IMP_Mailbox::MBOX_TEMPLATES))); $view->mbox_nomailbox = IMP_Mailbox::formTo(self::PREF_NO_MBOX); return $view->render('composetemplates'); }
/** */ public function display(Horde_Core_Prefs_Ui $ui) { global $injector, $prefs; $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/prefs')); $view->addHelper('FormTag'); $view->addHelper('Horde_Core_View_Helper_Label'); $view->addHelper('Tag'); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add($iterator::REMOTE); if (!($initial_page = $prefs->getValue('initial_page'))) { $initial_page = 'INBOX'; } $view->folder_page = IMP_Mailbox::formTo(IMP::INITIAL_FOLDERS); $view->folder_sel = $initial_page == IMP::INITIAL_FOLDERS; $view->flist = new IMP_Ftree_Select(array('inc_vfolder' => true, 'iterator' => $iterator, 'selected' => $initial_page)); return $view->render('initialpage'); }
/** */ public function display(Horde_Core_Prefs_Ui $ui) { global $injector, $page_output; $page_output->addScriptFile('folderprefs.js'); $identity = $injector->getInstance('IMP_Identity'); $js = array(); foreach ($identity->getAllSentmail(false) as $key => $val) { $js[$key] = $val->form_to; } $page_output->addInlineJsVars(array('ImpFolderPrefs.mboxes' => array('sent_mail' => _("Create a new sent-mail mailbox")), 'ImpFolderPrefs.sentmail' => $js)); $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/prefs')); $view->addHelper('Horde_Core_View_Helper_Label'); $view->default = IMP_Mailbox::formTo(self::PREF_DEFAULT); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add($iterator::NONIMAP); $iterator->mboxes = array('INBOX'); $view->flist = new IMP_Ftree_Select(array('basename' => true, 'iterator' => $iterator, 'new_mbox' => true)); $view->special_use = $this->_getSpecialUse(Horde_Imap_Client::SPECIALUSE_SENT); return $view->render('sentmail'); }
/** * URL Parameters: * - ts: (integer) Toggle subscribe view. */ protected function _init() { global $injector, $notification, $prefs, $session; $imp_imap = $injector->getInstance('IMP_Factory_Imap')->create(); /* Redirect back to the mailbox if folder use is not allowed. */ if (!$imp_imap->access(IMP_Imap::ACCESS_FOLDERS)) { $notification->push(_("The folder view is not enabled."), 'horde.error'); IMP_Minimal_Mailbox::url()->redirect(); } /* Decide whether or not to show all the unsubscribed mailboxes. */ $subscribe = $prefs->getValue('subscribe'); $showAll = !$subscribe || $session->get('imp', 'showunsub'); /* Toggle subscribed view, if necessary. */ if ($subscribe && $this->vars->ts) { $showAll = !$showAll; $session->set('imp', 'showunsub', $showAll); } /* Initialize the IMP_Ftree object. */ $ftree = $injector->getInstance('IMP_Ftree'); $iterator = new IMP_Ftree_IteratorFilter($ftree); $iterator->add($iterator::REMOTE); if ($showAll) { $ftree->loadUnsubscribed(); $iterator->remove($iterator::UNSUB); } $tree = $ftree->createTree('mimp_folders', array('iterator' => $iterator, 'poll_info' => true, 'render_type' => 'IMP_Tree_Simplehtml')); $selfurl = self::url(); $menu = array(array(_("Refresh"), $selfurl)); if ($subscribe) { $menu[] = array($showAll ? _("Show Subscribed Mailboxes") : _("Show All Mailboxes"), $selfurl->copy()->add('ts', 1)); } $this->title = _("Folders"); $this->view->menu = $this->getMenu('folders', $menu); $this->view->title = $this->title; $this->view->tree = $tree->getTree(true); $this->_pages[] = 'folders'; $this->_pages[] = 'menu'; }
/** * Create SELECT list of mailboxes for advanced search page. * * @param boolean $unsub Include unsubcribed mailboxes? * * @return object Object with the following properties: * - mbox_list: (array) Mapping of mailbox name (key) to display * string (values). * - tree: (IMP_Tree_Flist) Tree object. */ public function getSearchMboxList($unsub = false) { global $injector, $registry; $ob = new stdClass(); $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/search')); $view->allsearch = IMP_Mailbox::formTo(IMP_Search_Query::ALLSEARCH); $ftree = $injector->getInstance('IMP_Ftree'); $iterator = new IMP_Ftree_IteratorFilter($ftree); if ($unsub) { $ftree->loadUnsubscribed(); $iterator->remove($iterator::UNSUB); } if ($registry->getView() != $registry::VIEW_DYNAMIC) { $iterator->add($iterator::REMOTE); } $ob->tree = $ftree->createTree('imp_search', array('iterator' => $iterator, 'render_params' => array('abbrev' => 0, 'container_select' => true, 'customhtml' => $view->render('search-all'), 'heading' => _("Add search mailbox:")), 'render_type' => 'IMP_Tree_Flist')); $mbox_list = array(); foreach ($iterator as $val) { $mbox_ob = $val->mbox_ob; $mbox_list[$mbox_ob->form_to] = $mbox_ob->display; } $ob->mbox_list = $mbox_list; return $ob; }
/** */ protected function _init() { global $conf, $injector, $notification, $page_output, $prefs, $registry, $session; $mailbox = $this->indices->mailbox; $imp_imap = $mailbox->imp_imap; /* We know we are going to be exclusively dealing with this mailbox, * so select it on the IMAP server (saves some STATUS calls). Open R/W * to clear the RECENT flag. */ $imp_imap->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); /* Make sure we have a valid index. */ $imp_mailbox = $mailbox->list_ob; $imp_mailbox->setIndex($this->indices); if (!$imp_mailbox->isValidIndex()) { $this->_returnToMailbox(null, 'message_missing'); return; } $imp_flags = $injector->getInstance('IMP_Flags'); $imp_identity = $injector->getInstance('IMP_Identity'); $imp_message = $injector->getInstance('IMP_Message'); $imp_ui = $injector->getInstance('IMP_Message_Ui'); /* Run through action handlers. */ if ($this->vars->actionID) { try { $session->getToken($this->vars->token); } catch (Horde_Exception $e) { $notification->push($e); $this->vars->actionID = null; } } $readonly = $mailbox->readonly; $peek = false; switch ($this->vars->actionID) { case 'blacklist': case 'whitelist': if ($this->vars->actionID == 'blacklist') { $injector->getInstance('IMP_Filter')->blacklistMessage($this->indices); } else { $injector->getInstance('IMP_Filter')->whitelistMessage($this->indices); } break; case 'delete_message': $imp_message->delete($this->indices, array('mailboxob' => $imp_mailbox)); if ($prefs->getValue('mailbox_return')) { $this->_returnToMailbox($imp_mailbox->getIndex()); return; } if ($imp_ui->moveAfterAction($mailbox)) { $imp_mailbox->setIndex(1); } break; case 'undelete_message': $imp_message->undelete($this->indices); break; case 'move_message': case 'copy_message': if (isset($this->vars->targetMbox) && (!$readonly || $this->vars->actionID == 'copy_message')) { if ($this->vars->newMbox) { $targetMbox = IMP_Mailbox::prefFrom($this->vars->targetMbox); $newMbox = true; } else { $targetMbox = IMP_Mailbox::formFrom($this->vars->targetMbox); $newMbox = false; } $imp_message->copy($targetMbox, $this->vars->actionID == 'move_message' ? 'move' : 'copy', $this->indices, array('create' => $newMbox, 'mailboxob' => $imp_mailbox)); if ($prefs->getValue('mailbox_return')) { $this->_returnToMailbox($imp_mailbox->getIndex()); return; } } break; case 'innocent_report': case 'spam_report': $res = $injector->getInstance('IMP_Factory_Spam')->create($this->vars->actionID == 'spam_report' ? IMP_Spam::SPAM : IMP_Spam::INNOCENT)->report($this->indices, array('mailbox' => $imp_mailbox)); switch ($res) { case 1: if ($imp_ui->moveAfterAction($mailbox)) { $imp_mailbox->setIndex(1); } break; } if ($prefs->getValue('mailbox_return')) { $this->_returnToMailbox($imp_mailbox->getIndex()); return; } break; case 'flag_message': if (!$readonly && isset($this->vars->flag) && count($this->indices)) { $peek = true; $flag = $imp_flags->parseFormId($this->vars->flag); $imp_message->flag(array($flag['set'] ? 'add' : 'remove' => array($flag['flag'])), $this->indices); if ($prefs->getValue('mailbox_return')) { $this->_returnToMailbox($imp_mailbox->getIndex()); return; } } break; case 'add_address': try { $contact_link = $injector->getInstance('IMP_Contacts')->addAddress($this->vars->address, $this->vars->name); $notification->push(sprintf(_("Entry \"%s\" was successfully added to the address book"), $contact_link), 'horde.success', array('content.raw')); } catch (Horde_Exception $e) { $notification->push($e); } break; case 'strip_all': case 'strip_attachment': if (!$readonly) { try { $this->indices = new IMP_Indices_Mailbox($this->indices->mailbox, $imp_message->stripPart($this->indices, $this->vars->actionID == 'strip_all' ? null : $this->vars->imapid, array('mailboxob' => $imp_mailbox))); $notification->push(_("Attachment successfully stripped."), 'horde.success'); } catch (Horde_Exception $e) { $notification->push($e); } } break; } /* We may have done processing that has taken us past the end of the * message array, so we will return to the mailbox. */ if (!$imp_mailbox->isValidIndex()) { $this->_returnToMailbox(count($imp_mailbox)); return; } /* Now that we are done processing, get the index and array index of * the current message. */ $msg_index = $imp_mailbox[$imp_mailbox->getIndex()]; /* Parse the message. */ try { $imp_contents = $injector->getInstance('IMP_Factory_Contents')->create(new IMP_Indices($imp_mailbox)); } catch (IMP_Exception $e) { $imp_mailbox->removeMsgs(true); $this->_returnToMailbox(null, 'message_missing'); return; } /* Get envelope/flag/header information. */ try { /* Need to fetch flags before HEADERTEXT, because SEEN flag might * be set before we can grab it. */ $query = new Horde_Imap_Client_Fetch_Query(); $query->flags(); $flags_ret = $imp_imap->fetch($msg_index['m'], $query, array('ids' => $imp_imap->getIdsOb($msg_index['u']))); $query = new Horde_Imap_Client_Fetch_Query(); $query->envelope(); $fetch_ret = $imp_imap->fetch($msg_index['m'], $query, array('ids' => $imp_imap->getIdsOb($msg_index['u']))); } catch (IMP_Imap_Exception $e) { $this->_returnToMailbox(null, 'message_missing'); return; } $envelope = $fetch_ret->first()->getEnvelope(); $flags = $flags_ret->first()->getFlags(); $mime_headers = $peek ? $imp_contents->getHeader() : $imp_contents->getHeaderAndMarkAsSeen(); /* Get the title/mailbox label of the mailbox page. */ $page_label = $mailbox->label; /* Generate the link to ourselves. */ $buid = $imp_mailbox->getBuid($msg_index['m'], $msg_index['u']); $msgindex = $imp_mailbox->getIndex(); $message_url = Horde::url('basic.php')->add('page', 'message'); $token = $session->getToken(); $self_link = self::url(array('buid' => $buid, 'mailbox' => $mailbox))->add(array('token' => $token, 'start' => $msgindex)); /* Develop the list of headers to display. */ $basic_headers = $imp_ui->basicHeaders(); $display_headers = $msgAddresses = array(); $date_ob = new IMP_Message_Date($envelope->date); if ($format_date = $date_ob->format($date_ob::DATE_LOCAL)) { $display_headers['date'] = $format_date; } /* Build From address links. */ $display_headers['from'] = $imp_ui->buildAddressLinks($envelope->from, $self_link); /* Add country/flag image. */ if (!empty($envelope->from)) { $contacts_img = new IMP_Contacts_Image($envelope->from[0]); try { $res = $contacts_img->getImage($contacts_img::FLAG); $display_headers['from'] .= ' ' . Horde_Themes_Image::tag($res['url'], array('alt' => $res['desc'], 'fullsrc' => true)); } catch (IMP_Exception $e) { } } /* Look for Face information. */ if ($face = $mime_headers->getValue('face')) { $display_headers['from'] .= ' <img src="' . Horde_Url_Data::create('image/png', base64_decode($face)) . '">'; } /* Build To/Cc/Bcc links. */ foreach (array('to', 'cc', 'bcc') as $val) { $msgAddresses[] = $mime_headers->getValue($val); if ($val == 'to' || count($envelope->{$val})) { $display_headers[$val] = $imp_ui->buildAddressLinks($envelope->{$val}, $self_link); } } /* Process the subject now. */ if ($subject = $mime_headers->getValue('subject')) { $this->title = sprintf(_("%s: %s"), $page_label, $subject); $shortsub = Horde_String::truncate($subject, 100); } else { $shortsub = _("[No Subject]"); $this->title = sprintf(_("%s: %s"), $page_label, $shortsub); } /* See if the priority has been set. */ switch ($injector->getInstance('IMP_Mime_Headers')->getPriority($mime_headers)) { case 'high': $basic_headers['priority'] = _("Priority"); $display_headers['priority'] = '<div class="iconImg msgflags flagHighpriority" title="' . htmlspecialchars(_("High Priority")) . '"></div> ' . _("High"); break; case 'low': $basic_headers['priority'] = _("Priority"); $display_headers['priority'] = '<div class="iconImg msgflags flagLowpriority" title="' . htmlspecialchars(_("Low Priority")) . '"></div> ' . _("Low"); break; } /* Build Reply-To address link. */ if (!empty($envelope->reply_to) && $envelope->from[0]->bare_address != $envelope->reply_to[0]->bare_address && ($reply_to = $imp_ui->buildAddressLinks($envelope->reply_to, $self_link))) { $display_headers['reply-to'] = $reply_to; } /* Determine if all/list/user-requested headers needed. */ $all_headers = $this->vars->show_all_headers; $user_hdrs = $imp_ui->getUserHeaders(); /* Check for the presence of mailing list information. */ $list_info = $imp_ui->getListInformation($mime_headers); /* Display all headers or, optionally, the user-specified headers for * the current identity. */ $full_headers = array(); if ($all_headers) { $header_array = $mime_headers->toArray(); foreach ($header_array as $head => $val) { $lc_head = strtolower($head); /* Skip the header if we have already dealt with it. */ if (!isset($display_headers[$lc_head]) && (!in_array($lc_head, array('importance', 'x-priority')) || !isset($display_headers['priority']))) { $full_headers[$lc_head] = $val; } } } elseif (!empty($user_hdrs)) { foreach ($user_hdrs as $user_hdr) { $user_val = $mime_headers->getValue($user_hdr); if (!empty($user_val)) { $full_headers[$user_hdr] = $user_val; } } } ksort($full_headers); /* For the self URL link, we can't trust the index in the query string * as it may have changed if we deleted/copied/moved messages. We may * need other stuff in the query string, so we need to do an * add/remove of uid info. */ $selfURL = $mailbox->url(Horde::selfUrlParams()->remove(array('actionID')), $buid)->add('token', $token); $headersURL = $selfURL->copy()->remove(array('show_all_headers')); /* Generate previous/next links. */ $prev_msg = $imp_mailbox[$imp_mailbox->getIndex() - 1]; if ($prev_msg) { $prev_url = self::url(array('buid' => $imp_mailbox->getBuid($prev_msg['m'], $prev_msg['u']), 'mailbox' => $mailbox))->setRaw(true); $page_output->addLinkTag(array('href' => $prev_url, 'id' => 'prev', 'rel' => 'Previous', 'type' => null)); } else { $prev_url = null; } $next_msg = $imp_mailbox[$imp_mailbox->getIndex() + 1]; if ($next_msg) { $next_url = self::url(array('buid' => $imp_mailbox->getBuid($next_msg['m'], $next_msg['u']), 'mailbox' => $mailbox))->setRaw(true); $page_output->addLinkTag(array('href' => $next_url, 'id' => 'next', 'rel' => 'Next', 'type' => null)); } else { $next_url = null; } /* Generate the mailbox link. */ $mailbox_url = $mailbox->url('mailbox')->add('start', $msgindex); /* Everything below here is related to preparing the output. */ $js_vars = array('ImpMessage.text' => array('innocent_report' => _("Are you sure you wish to report this message as innocent?"), 'moveconfirm' => _("Are you sure you want to move the message(s)? (Some message information might get lost, like message headers, text formatting or attachments!)"), 'newmbox' => _("You are copying/moving to a new mailbox.") . "\n" . _("Please enter a name for the new mailbox:") . "\n", 'spam_report' => _("Are you sure you wish to report this message as spam?"), 'target_mbox' => _("You must select a target mailbox first."))); /* Set the status information of the message. */ $msgAddresses[] = $mime_headers->getValue('from'); $identity = $match_identity = $imp_identity->getMatchingIdentity($msgAddresses); if (is_null($identity)) { $identity = $imp_identity->getDefault(); } $flag_parse = $imp_flags->parse(array('flags' => $flags, 'personal' => $match_identity)); $status = ''; foreach ($flag_parse as $val) { if ($val instanceof IMP_Flag_User) { $status .= '<span class="' . $val->css . '" style="' . ($val->bgdefault ? '' : 'background:' . htmlspecialchars($val->bgcolor) . ';') . 'color:' . htmlspecialchars($val->fgcolor) . '">' . htmlspecialchars($val->label) . '</span>'; } else { $status .= $val->span; } } /* If this is a search mailbox, display a link to the parent mailbox * of the message in the header. */ $h_page_label = htmlspecialchars($page_label); $header_label = $h_page_label; if ($mailbox->search) { $header_label .= ' [' . $msg_index['m']->url('mailbox')->link() . $msg_index['m']->display_html . '</a>]'; } /* Prepare the navbar top template. */ $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/basic/message')); $view->addHelper('FormTag'); $view->addHelper('Tag'); $t_view = clone $view; $t_view->buid = $buid; $t_view->message_url = $message_url; $t_view->mailbox = $mailbox->form_to; $t_view->start = $msgindex; $t_view->token = $token; /* Prepare the navbar navigate template. */ $n_view = clone $view; $n_view->readonly = $readonly; $n_view->id = 1; if ($mailbox->access_flags) { $n_view->mailbox = $mailbox->form_to; $args = array('imap' => true, 'mailbox' => $mailbox); $form_set = $form_unset = array(); foreach ($imp_flags->getList($args) as $val) { if ($val->canset) { $form_set[] = array('f' => $val->form_set, 'l' => $val->label); $form_unset[] = array('f' => $val->form_unset, 'l' => $val->label); } } $n_view->flaglist_set = $form_set; $n_view->flaglist_unset = $form_unset; } if ($imp_imap->access(IMP_Imap::ACCESS_FOLDERS)) { $n_view->move = Horde::widget(array('url' => '#', 'class' => 'moveAction', 'title' => _("Move"), 'nocheck' => true)); $n_view->copy = Horde::widget(array('url' => '#', 'class' => 'copyAction', 'title' => _("Copy"), 'nocheck' => true)); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add($iterator::NONIMAP); $n_view->options = new IMP_Ftree_Select(array('heading' => _("This message to"), 'inc_tasklists' => true, 'inc_notepads' => true, 'iterator' => $iterator, 'new_mbox' => true)); } $n_view->back_to = Horde::widget(array('url' => $mailbox_url, 'title' => sprintf(_("Bac_k to %s"), $h_page_label), 'nocheck' => true)); if ($prev_url) { $n_view->prev = Horde::link($prev_url, _("Previous Message")); $n_view->prev_img = 'navleftImg'; } else { $n_view->prev_img = 'navleftgreyImg'; } if ($next_url) { $n_view->next = Horde::link($next_url, _("Next Message")); $n_view->next_img = 'navrightImg'; } else { $n_view->next_img = 'navrightgreyImg'; } /* Prepare the navbar actions template. */ $a_view = clone $view; $compose_params = array('buid' => $buid, 'identity' => $identity, 'mailbox' => IMP_Mailbox::formTo($mailbox)); if (!$prefs->getValue('compose_popup')) { $compose_params['start'] = $msgindex; } if ($msg_index['m']->access_deletemsgs) { if (in_array(Horde_Imap_Client::FLAG_DELETED, $flags)) { $a_view->delete = Horde::widget(array('url' => $self_link->copy()->add('actionID', 'undelete_message'), 'title' => _("Undelete"), 'nocheck' => true)); } else { $a_view->delete = Horde::widget(array('url' => $self_link->copy()->add('actionID', 'delete_message'), 'title' => _("_Delete"), 'nocheck' => true)); if (!$msg_index['m']->is_imap) { $js_vars['ImpMessage.pop3delete'] = _("Are you sure you want to PERMANENTLY delete these messages?"); } } } $disable_compose = !IMP_Compose::canCompose(); if (!$disable_compose) { $clink_ob = new IMP_Compose_Link(); $clink = $clink_ob->link()->add($compose_params); $a_view->reply = Horde::widget(array('url' => $clink->add(array('actionID' => 'reply_auto')), 'class' => 'horde-hasmenu', 'title' => _("_Reply"), 'nocheck' => true)); $a_view->reply_sender = Horde::widget(array('url' => $clink->add(array('actionID' => 'reply')), 'title' => _("To Sender"), 'nocheck' => true)); if ($list_info['reply_list']) { $a_view->reply_list = Horde::widget(array('url' => $clink->add(array('actionID' => 'reply_list')), 'title' => _("To _List"), 'nocheck' => true)); } $addr_ob = clone $envelope->to; $addr_ob->add($envelope->cc); $addr_ob->setIteratorFilter(0, $imp_identity->getAllFromAddresses()); if (count($addr_ob)) { $a_view->show_reply_all = Horde::widget(array('url' => $clink->add(array('actionID' => 'reply_all')), 'title' => _("To _All"), 'nocheck' => true)); } $fwd_locked = $prefs->isLocked('forward_default'); $a_view->forward = Horde::widget(array('url' => $clink->add(array('actionID' => 'forward_auto')), 'class' => $fwd_locked ? '' : ' horde-hasmenu', 'title' => _("Fo_rward"), 'nocheck' => true)); if (!$fwd_locked) { $a_view->forward_attach = Horde::widget(array('url' => $clink->add(array('actionID' => 'forward_attach')), 'title' => _("As Attachment"), 'nocheck' => true)); $a_view->forward_body = Horde::widget(array('url' => $clink->add(array('actionID' => 'forward_body')), 'title' => _("In Body Text"), 'nocheck' => true)); $a_view->forward_both = Horde::widget(array('url' => $clink->add(array('actionID' => 'forward_both')), 'title' => _("Attachment and Body Text"), 'nocheck' => true)); } $a_view->redirect = Horde::widget(array('url' => $clink->add(array('actionID' => 'redirect_compose')), 'title' => _("Redirec_t"), 'nocheck' => true)); $a_view->editasnew = Horde::widget(array('url' => $clink->add(array('actionID' => 'editasnew')), 'title' => _("Edit as New"), 'nocheck' => true)); } if ($mailbox->access_sortthread) { $a_view->show_thread = Horde::widget(array('url' => $mailbox->url(IMP_Basic_Thread::url(), $buid)->add(array('start' => $msgindex)), 'title' => _("_View Thread"), 'nocheck' => true)); } if (!$readonly && $registry->hasMethod('mail/blacklistFrom')) { $a_view->blacklist = Horde::widget(array('url' => $self_link->copy()->add('actionID', 'blacklist'), 'title' => _("_Blacklist"), 'nocheck' => true)); } if (!$readonly && $registry->hasMethod('mail/whitelistFrom')) { $a_view->whitelist = Horde::widget(array('url' => $self_link->copy()->add('actionID', 'whitelist'), 'title' => _("_Whitelist"), 'nocheck' => true)); } if (!empty($conf['user']['allow_view_source'])) { $a_view->view_source = $imp_contents->linkViewJS($imp_contents->getMIMEMessage(), 'view_source', _("_Message Source"), array('css' => '', 'jstext' => _("Message Source"), 'widget' => true)); } if (!$disable_compose && (in_array(Horde_Imap_Client::FLAG_DRAFT, $flags) || $msg_index['m']->drafts)) { $a_view->resume = Horde::widget(array('url' => $clink->add(array('actionID' => 'draft')), 'title' => _("Resume"), 'nocheck' => true)); } $imp_params = $mailbox->urlParams($buid); $a_view->save_as = Horde::widget(array('url' => IMP_Contents_View::downloadUrl($subject, array_merge(array('actionID' => 'save_message'), $imp_params)), 'title' => _("Sa_ve as"), 'nocheck' => true)); if ($msg_index['m']->spam_show) { $a_view->spam = Horde::widget(array('url' => '#', 'class' => 'spamAction', 'title' => _("Report as Spam"), 'nocheck' => true)); } if ($msg_index['m']->innocent_show) { $a_view->innocent = Horde::widget(array('url' => '#', 'class' => 'innocentAction', 'title' => _("Report as Innocent"), 'nocheck' => true)); } if (!$disable_compose) { $a_view->redirect = Horde::widget(array('url' => $clink->add(array('actionID' => 'redirect_compose')), 'title' => _("Redirec_t"), 'nocheck' => true)); } $a_view->headers = Horde::widget(array('url' => '#', 'class' => 'horde-hasmenu', 'title' => _("Headers"), 'nocheck' => true)); if ($all_headers) { $a_view->common_headers = Horde::widget(array('url' => $headersURL, 'title' => _("Show Common Headers"), 'nocheck' => true)); } if (!$all_headers) { $a_view->all_headers = Horde::widget(array('url' => $headersURL->copy()->add('show_all_headers', 1), 'title' => _("Show All Headers"), 'nocheck' => true)); } if ($list_info['exists']) { $a_view->list_headers = Horde::widget(array('onclick' => Horde::popupJs(IMP_Basic_Listinfo::url(array('buid' => $buid, 'mailbox' => $mailbox)), array('urlencode' => true)), 'title' => _("Show Mailing List Information"), 'nocheck' => true)); } $hdrs = array(); /* Prepare the main message template. */ if (!$all_headers) { foreach ($display_headers as $head => $val) { $hdrs[] = array('name' => $basic_headers[$head], 'val' => $val); } } foreach ($full_headers as $head => $val) { if (is_array($val)) { $hdrs[] = array('name' => $head, 'val' => '<ul style="margin:0;padding-left:15px"><li>' . implode("</li>\n<li>", array_map('htmlspecialchars', $val)) . '</li></ul>'); } else { $hdrs[] = array('name' => $head, 'val' => htmlspecialchars($val)); } } /* Determine the fields that will appear in the MIME info entries. */ $part_info = $part_info_display = array('icon', 'description', 'size'); $part_info_action = array('download', 'download_zip', 'img_save', 'strip'); $part_info_bodyonly = array('print'); $show_parts = isset($this->vars->show_parts) ? $this->vars->show_parts : $prefs->getValue('parts_display'); $part_info_display = array_merge($part_info_display, $part_info_action, $part_info_bodyonly); $contents_mask = IMP_Contents::SUMMARY_BYTES | IMP_Contents::SUMMARY_SIZE | IMP_Contents::SUMMARY_ICON | IMP_Contents::SUMMARY_DESCRIP_LINK | IMP_Contents::SUMMARY_DOWNLOAD | IMP_Contents::SUMMARY_DOWNLOAD_ZIP | IMP_Contents::SUMMARY_IMAGE_SAVE | IMP_Contents::SUMMARY_PRINT; /* Do MDN processing now. */ $mdntext = $imp_ui->MDNCheck(new IMP_Indices($msg_index['m'], $buid), $mime_headers, $this->vars->mdn_confirm) ? strval(new IMP_Mime_Status(array(_("The sender of this message is requesting a notification from you when you have read this message."), sprintf(_("Click %s to send the notification message."), Horde::link($selfURL->copy()->add('mdn_confirm', 1)) . _("HERE") . '</a>')))) : ''; /* Build body text. This needs to be done before we build the * attachment list that lives in the header. */ $inlineout = $imp_contents->getInlineOutput(array('mask' => $contents_mask, 'part_info_display' => $part_info_display, 'show_parts' => $show_parts)); /* Build the Attachments menu. */ $show_atc = false; switch ($show_parts) { case 'atc': $a_view->show_parts_all = Horde::widget(array('url' => $headersURL->copy()->add(array('show_parts' => 'all')), 'title' => _("Show All Parts"), 'nocheck' => true)); $show_atc = true; break; case 'all': if ($prefs->getValue('strip_attachments')) { $js_vars['ImpMessage.text']['stripwarn'] = _("Are you sure you wish to PERMANENTLY delete this attachment?"); } break; } if (count($inlineout['atc_parts']) > 2) { $a_view->download_all = Horde::widget(array('url' => $imp_contents->urlView($imp_contents->getMIMEMessage(), 'download_all'), 'title' => _("Download All Attachments (in .zip file)"), 'nocheck' => true)); if ($prefs->getValue('strip_attachments')) { $a_view->strip_all = Horde::widget(array('url' => Horde::selfUrlParams()->add(array('actionID' => 'strip_all', 'token' => $token)), 'class' => 'stripAllAtc', 'title' => _("Strip All Attachments"), 'nocheck' => true)); $js_vars['ImpMessage.text']['stripallwarn'] = _("Are you sure you want to PERMANENTLY delete all attachments?"); } $show_atc = true; } if ($show_atc) { $a_view->atc = Horde::widget(array('url' => '#', 'class' => 'horde-hasmenu', 'title' => _("Attachments"), 'nocheck' => true)); } /* Show attachment information in headers? 'atc_parts' will be empty if * 'parts_display' pref is 'none'. */ if (!empty($inlineout['atc_parts'])) { if ($show_parts == 'all') { $val = $imp_contents->getTree()->getTree(true); } else { $tmp = array(); foreach ($inlineout['atc_parts'] as $id) { $summary = $imp_contents->getSummary($id, $contents_mask); $tmp[] = '<tr>'; foreach ($part_info as $val) { $tmp[] = '<td>' . $summary[$val] . '</td>'; } $tmp[] = '<td>'; foreach ($part_info_action as $val) { $tmp[] = $summary[$val]; } $tmp[] = '</td></tr>'; } $val = '<table>' . implode('', $tmp) . '</table>'; } $hdrs[] = array('class' => 'msgheaderParts', 'name' => $show_parts == 'all' ? _("Parts") : _("Attachments"), 'val' => $val); } $m_view = clone $view; $m_view->label = $shortsub; $m_view->headers = $hdrs; $m_view->msgtext = $mdntext . $inlineout['msgtext']; $subinfo = new IMP_View_Subinfo(array('mailbox' => $mailbox)); $subinfo->label = $header_label; $subinfo->value = sprintf(_("(%d of %d)"), $msgindex, count($imp_mailbox)) . $status; $injector->getInstance('Horde_View_Topbar')->subinfo = $subinfo->render(); /* Output message page now. */ $page_output->addInlineJsVars($js_vars, array('top' => true)); $page_output->addScriptFile('scriptaculous/effects.js', 'horde'); $page_output->addScriptFile('hordecore.js', 'horde'); $page_output->addScriptFile('message.js'); $page_output->addScriptFile('stripe.js', 'horde'); $page_output->addScriptPackage('IMP_Script_Package_Imp'); if (!empty($conf['tasklist']['use_notepad']) || !empty($conf['tasklist']['use_tasklist'])) { $page_output->addScriptPackage('Horde_Core_Script_Package_Dialog'); } $page_output->noDnsPrefetch(); Horde::startBuffer(); foreach ($injector->getInstance('IMP_Maillog')->getLog(new IMP_Maillog_Message($this->indices, array('mdn'))) as $val) { $notification->push($val->message, 'imp.' . $val->action); } $this->output = Horde::endBuffer(); $this->output .= $t_view->render('navbar_top') . $n_view->render('navbar_navigate') . $a_view->render('navbar_actions') . $m_view->render('message') . $a_view->render('navbar_actions'); $n_view->id = 2; $n_view->isbottom = true; $this->output .= $n_view->render('navbar_navigate'); }
/** * Returns the list of mailboxes. * * @return array The list of IMAP mailboxes. A list of arrays with the * following keys: * - d: (string) The namespace delimiter. * - label: (string) Human readable label (UTF-8). * - level: (integer) The child level of this element. * - ob: (Horde_Imap_Client_Mailbox) A mailbox object. * - subscribed: (boolean) True if mailbox is subscribed (@since 6.2.0). */ public function mailboxList() { global $injector; $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add(array($iterator::CONTAINERS, $iterator::REMOTE, $iterator::VFOLDER)); $mboxes = array(); foreach ($iterator as $val) { $mbox_ob = $val->mbox_ob; $sub = $mbox_ob->sub; $mboxes[] = array('a' => $sub ? 8 : 0, 'd' => $mbox_ob->namespace_delimiter, 'label' => $mbox_ob->label, 'level' => $val->level, 'ob' => $mbox_ob->imap_mbox_ob, 'subscribed' => $sub); } return $mboxes; }
/** */ protected function _init() { global $injector, $notification, $page_output, $prefs, $registry, $session; $mailbox = $this->indices->mailbox; /* Call the mailbox redirection hook, if requested. */ try { $redirect = $injector->getInstance('Horde_Core_Hooks')->callHook('mbox_redirect', 'imp', array($mailbox)); if (!empty($redirect)) { Horde::url($redirect, true)->redirect(); } } catch (Horde_Exception_HookNotSet $e) { } $mailbox_url = Horde::url('basic.php')->add('page', 'mailbox'); $mailbox_imp_url = $mailbox->url('mailbox')->add('newmail', 1); $imp_flags = $injector->getInstance('IMP_Flags'); $imp_imap = $mailbox->imp_imap; $imp_search = $injector->getInstance('IMP_Search'); /* Run through the action handlers */ if (($actionID = $this->vars->actionID) && $actionID != 'message_missing') { try { $session->checkToken($this->vars->token); } catch (Horde_Exception $e) { $notification->push($e); $actionID = null; } } /* We know we are going to be exclusively dealing with this mailbox, * so select it on the IMAP server (saves some STATUS calls). Open * R/W to clear the RECENT flag. This call will catch invalid * mailboxes. */ $imp_imap->openMailbox($mailbox, Horde_Imap_Client::OPEN_READWRITE); $imp_mailbox = $mailbox->list_ob; /* Determine if mailbox is readonly. */ $readonly = $mailbox->readonly; switch ($actionID) { case 'change_sort': $mailbox->setSort($this->vars->sortby, $this->vars->sortdir); break; case 'blacklist': $injector->getInstance('IMP_Filter')->blacklistMessage($this->indices); break; case 'whitelist': $injector->getInstance('IMP_Filter')->whitelistMessage($this->indices); break; case 'spam_report': $injector->getInstance('IMP_Factory_Spam')->create(IMP_Spam::SPAM)->report($this->indices); break; case 'innocent_report': $injector->getInstance('IMP_Factory_Spam')->create(IMP_Spam::INNOCENT)->report($this->indices); break; case 'message_missing': $notification->push(_("Requested message not found."), 'horde.error'); break; case 'fwd_digest': case 'redirect_messages': case 'template_edit': if (count($this->indices)) { $compose_actions = array('fwd_digest' => 'fwd_digest', 'redirect_messages' => 'redirect_compose', 'template_edit' => 'template_edit'); $clink = new IMP_Compose_Link($this->vars); $options = array_merge(array('actionID' => $compose_actions[$actionID], 'muid' => strval($this->indices)), $clink->args); if ($prefs->getValue('compose_popup')) { $page_output->addInlineScript(array(Horde::popupJs(IMP_Basic_Compose::url(), array('novoid' => true, 'params' => array_merge(array('popup' => 1), $options)))), true); } else { IMP_Basic_Compose::url()->add($options)->redirect(); } } break; case 'delete_messages': $injector->getInstance('IMP_Message')->delete($this->indices, array('mailboxob' => $imp_mailbox)); break; case 'undelete_messages': $injector->getInstance('IMP_Message')->undelete($this->indices); break; case 'move_messages': case 'copy_messages': if (isset($this->vars->targetMbox) && count($this->indices) && (!$readonly || $actionID == 'copy_messages')) { $targetMbox = IMP_Mailbox::formFrom($this->vars->targetMbox); if (!empty($this->vars->newMbox) && $this->vars->newMbox == 1) { $targetMbox = IMP_Mailbox::get($this->vars->targetMbox)->namespace_append; $newMbox = true; } else { $targetMbox = IMP_Mailbox::formFrom($this->vars->targetMbox); $newMbox = false; } $injector->getInstance('IMP_Message')->copy($targetMbox, $actionID == 'move_messages' ? 'move' : 'copy', $this->indices, array('create' => $newMbox, 'mailboxob' => $imp_mailbox)); } break; case 'flag_messages': if (!$readonly && $this->vars->flag && count($this->indices)) { $flag = $imp_flags->parseFormId($this->vars->flag); $injector->getInstance('IMP_Message')->flag(array($flag['set'] ? 'add' : 'remove' => array($flag['flag'])), $this->indices); } break; case 'filter_messages': if (!$readonly) { $filter = IMP_Mailbox::formFrom($this->vars->filter); $q_ob = null; if (strpos($filter, self::FLAG_FILTER_PREFIX) === 0) { /* Flag filtering. */ $flag_filter = $imp_flags->parseFormId(substr($filter, strpos($filter, "") + 1)); try { $q_ob = $imp_search->createQuery(array(new IMP_Search_Element_Flag($flag_filter['flag'], $flag_filter['set'])), array('mboxes' => array($mailbox), 'type' => IMP_Search::CREATE_QUERY)); } catch (InvalidArgumentException $e) { } } else { /* Pre-defined filters. */ try { $q_ob = $imp_search->applyFilter($filter, array($mailbox)); } catch (InvalidArgumentException $e) { } } if ($q_ob) { IMP_Mailbox::get($q_ob)->url('mailbox')->redirect(); exit; } } break; case 'hide_deleted': $mailbox->setHideDeletedMsgs(!$prefs->getValue('delhide')); break; case 'expunge_mailbox': $injector->getInstance('IMP_Message')->expungeMailbox(array(strval($mailbox) => 1), array('mailboxob' => $imp_mailbox)); break; case 'filter': $mailbox->filter(); break; case 'empty_mailbox': $injector->getInstance('IMP_Message')->emptyMailbox(array(strval($mailbox))); break; case 'view_messages': $mailbox->url(IMP_Basic_Thread::url(), null, false)->add(array('mode' => 'msgview', 'muid' => strval($this->indices)))->redirect(); break; } /* Token to use in requests. */ $token = $session->getToken(); $search_mbox = $mailbox->search; /* Deal with filter options. */ if (!$readonly && IMP_Filter::canApplyFilters() && !$mailbox->filterOnDisplay() && ($mailbox->inbox || $prefs->getValue('filter_any_mailbox') && !$search_mbox)) { $filter_url = $mailbox_imp_url->copy()->add(array('actionID' => 'filter', 'token' => $token)); } /* Generate folder options list. */ if ($imp_imap->access(IMP_Imap::ACCESS_FOLDERS)) { $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add($iterator::NONIMAP); $folder_options = new IMP_Ftree_Select(array('heading' => _("Messages to"), 'inc_notepads' => true, 'inc_tasklists' => true, 'iterator' => $iterator, 'new_mbox' => true)); } /* Build the list of messages in the mailbox. */ $pageOb = $imp_mailbox->buildMailboxPage($this->vars->mpage, $this->vars->start); $show_preview = $prefs->getValue('preview_enabled'); $mbox_info = $imp_mailbox->getMailboxArray(range($pageOb['begin'], $pageOb['end']), array('headers' => true, 'preview' => (int) $show_preview, 'type' => $prefs->getValue('atc_flag'))); /* Determine sorting preferences. */ $sortpref = $mailbox->getSort(); $thread_sort = $sortpref->sortby == Horde_Imap_Client::SORT_THREAD; /* Determine if we are going to show the Hide/Purge Deleted Message * links. */ if (!($use_trash = $prefs->getValue('use_trash')) && !$mailbox->vinbox) { $showdelete = array('hide' => true, 'purge' => $mailbox->access_expunge); } else { $showdelete = array('hide' => false, 'purge' => false); } if ($showdelete['hide'] && !$prefs->isLocked('delhide')) { if ($prefs->getValue('delhide')) { $deleted_prompt = _("Show Deleted"); } else { $deleted_prompt = _("Hide Deleted"); } } /* Generate paging links. */ if ($pageOb['pagecount']) { if ($pageOb['page'] == 1) { $url_first = $url_prev = null; $pages_first = 'navfirstgreyImg'; $pages_prev = 'navleftgreyImg'; } else { $url_first = $mailbox_imp_url->copy()->add('mpage', 1); $pages_first = 'navfirstImg'; $url_prev = $mailbox_imp_url->copy()->add('mpage', $pageOb['page'] - 1); $pages_prev = 'navleftImg'; } if ($pageOb['page'] == $pageOb['pagecount']) { $url_last = $url_next = null; $pages_last = 'navlastgreyImg'; $pages_next = 'navrightgreyImg'; } else { $url_next = $mailbox_imp_url->copy()->add('mpage', $pageOb['page'] + 1); $pages_next = 'navrightImg'; $url_last = $mailbox_imp_url->copy()->add('mpage', $pageOb['pagecount']); $pages_last = 'navlastImg'; } } /* Generate RSS link. */ if ($mailbox->inbox) { $rss_box = ''; } else { $ns_info = $mailbox->namespace_info; if (is_null($ns_info)) { $rss_box = null; } else { $rss_box = str_replace(rawurlencode($ns_info->delimiter), '/', rawurlencode($ns_info->delimiter . ($ns_info->type == $ns_info::NS_PERSONAL ? $ns_info->stripNamespace($mailbox) : $mailbox))); } } if (!is_null($rss_box)) { $page_output->addLinkTag(array('href' => Horde::url('rss.php', true, -1) . $rss_box)); } /* If user wants the mailbox to be refreshed, set time here. */ $refresh_url = $mailbox_imp_url->copy()->add('mpage', $pageOb['page']); if (isset($filter_url)) { $filter_url->add('mpage', $pageOb['page']); } /* Determine if we are showing previews. */ $preview_tooltip = $show_preview ? $prefs->getValue('preview_show_tooltip') : false; if (!$preview_tooltip) { $strip_preview = $prefs->getValue('preview_strip_nl'); } $unread = $imp_mailbox->unseenMessages(Horde_Imap_Client::SEARCH_RESULTS_COUNT); $page_output->addInlineJsVars(array('ImpMailbox.pop3' => intval(!$mailbox->is_imap), 'ImpMailbox.text' => array('delete_messages' => _("Are you sure you wish to PERMANENTLY delete these messages?"), 'delete_all' => _("Are you sure you wish to delete all mail in this mailbox?"), 'delete_vfolder' => _("Are you sure you want to delete this Virtual Folder Definition?"), 'innocent_report' => _("Are you sure you wish to report this message as innocent?"), 'moveconfirm' => _("Are you sure you want to move the message(s)? (Some message information might get lost, like message headers, text formatting or attachments!)"), 'newmbox' => _("You are copying/moving to a new mailbox.") . "\n" . _("Please enter a name for the new mailbox:") . "\n", 'no' => _("No"), 'selectone' => _("You must select at least one message first."), 'selectonlyone' => _("You must select only one message for this action."), 'spam_report' => _("Are you sure you wish to report this message as spam?"), 'submit' => _("You must select at least one message first."), 'target_mbox' => _("You must select a target mailbox first.")), 'ImpMailbox.unread' => intval($unread))); $pagetitle = $this->title = $mailbox->label; if ($mailbox->editvfolder) { $query_text = wordwrap($imp_search[$mailbox]->querytext); $pagetitle .= ' [' . Horde::linkTooltip('#', $query_text, '', '', '', $query_text) . _("Virtual Folder") . '</a>]'; $this->title .= ' [' . _("Virtual Folder") . ']'; } elseif ($mailbox->editquery) { $query_text = wordwrap($imp_search[$mailbox]->querytext); $pagetitle = Horde::linkTooltip('#', $query_text, '', '', '', $query_text) . $pagetitle . '</a>'; } else { $pagetitle = $this->title = htmlspecialchars($this->title); } /* Generate mailbox summary string. */ $subinfo = new IMP_View_Subinfo(array('mailbox' => $mailbox)); $subinfo->value = $pagetitle . ' ('; if (empty($pageOb['end'])) { $subinfo->value .= _("No Messages"); } else { $subinfo->value .= $pageOb['pagecount'] > 1 ? sprintf(_("%d Messages"), $pageOb['msgcount']) . ' / ' . sprintf(_("Page %d of %d"), $pageOb['page'], $pageOb['pagecount']) : sprintf(_("%d Messages"), $pageOb['msgcount']); } $subinfo->value .= ')'; $injector->getInstance('Horde_View_Topbar')->subinfo = $subinfo->render(); $page_output->addScriptFile('hordecore.js', 'horde'); $page_output->addScriptFile('mailbox.js'); $page_output->addScriptPackage('Horde_Core_Script_Package_Dialog'); $page_output->metaRefresh($prefs->getValue('refresh_time'), $refresh_url); /* Prepare the header template. */ $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/basic/mailbox')); $view->addHelper('FormTag'); $view->addHelper('Horde_Core_View_Helper_Accesskey'); $view->addHelper('Tag'); $hdr_view = clone $view; $hdr_view->readonly = $readonly; $hdr_view->refresh_url = $refresh_url; if (isset($filter_url)) { $hdr_view->filter_url = $filter_url; } if ($mailbox->access_search) { if (!$search_mbox) { $hdr_view->search_url = $mailbox->url(IMP_Basic_Searchbasic::url()); } else { if ($mailbox->editvfolder) { $edit_search = _("Edit Virtual Folder"); } elseif ($mailbox->query) { if ($mailbox->editquery) { $edit_search = _("Edit Search Query"); } else { /* Basic search results. */ $search_mailbox = IMP_Mailbox::get($imp_search[$mailbox]->mboxes[0]); $hdr_view->search_url = $search_mailbox->url(IMP_Basic_Searchbasic::url()); $hdr_view->searchclose = $search_mailbox->url('mailbox'); } } if (isset($edit_search)) { $hdr_view->edit_search_url = $imp_search->editUrl($mailbox); $hdr_view->edit_search_title = $edit_search; } } } if ($mailbox->access_empty) { $hdr_view->empty = $mailbox_imp_url->copy()->add(array('actionID' => 'empty_mailbox', 'token' => $token)); } $this->output = $hdr_view->render('header'); /* If no messages, exit immediately. */ if (empty($pageOb['end'])) { if ($pageOb['anymsg'] && isset($deleted_prompt)) { /* Show 'Show Deleted' prompt if mailbox has no viewable * message but has hidden, deleted messages. */ $del_view = clone $view; $del_view->hide = Horde::widget(array('url' => $refresh_url->copy()->add(array('actionID' => 'hide_deleted', 'token' => $token)), 'class' => 'hideAction', 'title' => $deleted_prompt)); if ($mailbox->access_expunge) { $del_view->purge = Horde::widget(array('url' => $refresh_url->copy()->add(array('actionID' => 'expunge_mailbox', 'token' => $token)), 'class' => 'purgeAction', 'title' => _("Pur_ge Deleted"))); } $this->output .= $del_view->render('actions_deleted'); } $empty_view = clone $view; $empty_view->search_mbox = $search_mbox; $this->output .= $empty_view->render('empty_mailbox'); return; } $clink_ob = new IMP_Compose_Link(); $clink = $clink_ob->link(); /* Display the navbar and actions if there is at least 1 message in * mailbox. */ if ($pageOb['msgcount']) { /* Prepare the navbar template. */ $n_view = clone $view; $n_view->id = 1; $n_view->readonly = $readonly; $filtermsg = false; if ($mailbox->access_flags) { $args = array('imap' => true, 'mailbox' => $search_mbox ? null : $mailbox); $form_set = $form_unset = array(); foreach ($imp_flags->getList($args) as $val) { if ($val->canset) { $form_set[] = array('f' => $val->form_set, 'l' => $val->label, 'v' => IMP_Mailbox::formTo(self::FLAG_FILTER_PREFIX . $val->form_set)); $form_unset[] = array('f' => $val->form_unset, 'l' => $val->label, 'v' => IMP_Mailbox::formTo(self::FLAG_FILTER_PREFIX . $val->form_unset)); } } $n_view->flaglist_set = $form_set; $n_view->flaglist_unset = $form_unset; if (!$search_mbox && $mailbox->access_search) { $filtermsg = $n_view->flag_filter = true; } } if (!$search_mbox && $mailbox->access_filters) { $filters = array(); $iterator = IMP_Search_IteratorFilter::create(IMP_Search_IteratorFilter::FILTER); foreach ($iterator as $val) { $filters[] = array('l' => $val->label, 'v' => IMP_Mailbox::formTo($val)); } if (!empty($filters)) { $filtermsg = true; $n_view->filters = $filters; } } $n_view->filtermsg = $filtermsg; if ($imp_imap->access(IMP_Imap::ACCESS_FOLDERS)) { $n_view->move = Horde::widget(array('url' => '#', 'class' => 'moveAction', 'title' => _("Move"), 'nocheck' => true)); $n_view->copy = Horde::widget(array('url' => '#', 'class' => 'copyAction', 'title' => _("Copy"), 'nocheck' => true)); $n_view->folder_options = $folder_options; } $n_view->mailbox_url = $mailbox_url; $n_view->mailbox = $mailbox->form_to; if ($pageOb['pagecount'] > 1) { $n_view->multiple_page = true; $n_view->pages_first = $pages_first; $n_view->url_first = $url_first; $n_view->pages_prev = $pages_prev; $n_view->url_prev = $url_prev; $n_view->pages_next = $pages_next; $n_view->url_next = $url_next; $n_view->pages_last = $pages_last; $n_view->url_last = $url_last; $n_view->page_val = $pageOb['page']; $n_view->page_size = Horde_String::length($pageOb['pagecount']); } $this->output .= $n_view->render('navbar'); /* Prepare the actions template. */ $a_view = clone $view; if ($mailbox->access_deletemsgs) { $del_class = $use_trash && $mailbox->trash ? 'permdeleteAction' : 'deleteAction'; $a_view->delete = Horde::widget(array('url' => '#', 'class' => $del_class, 'title' => _("_Delete"))); } if ($showdelete['purge'] || $mailbox->vtrash) { $a_view->undelete = Horde::widget(array('url' => '#', 'class' => 'undeleteAction', 'title' => _("_Undelete"))); } $mboxactions = array(); if ($showdelete['purge']) { $mailbox_link = $mailbox_imp_url->copy()->add('mpage', $pageOb['page']); if (isset($deleted_prompt)) { $mboxactions[] = Horde::widget(array('url' => $mailbox_link->copy()->add(array('actionID' => 'hide_deleted', 'token' => $token)), 'class' => 'hideAction', 'title' => $deleted_prompt)); } $mboxactions[] = Horde::widget(array('url' => $mailbox_link->copy()->add(array('actionID' => 'expunge_mailbox', 'token' => $token)), 'class' => 'purgeAction', 'title' => _("Pur_ge Deleted"))); } if (!$sortpref->sortby_locked && $sortpref->sortby != Horde_Imap_Client::SORT_SEQUENCE) { $mboxactions[] = Horde::widget(array('url' => $mailbox_imp_url->copy()->add(array('sortby' => Horde_Imap_Client::SORT_SEQUENCE, 'actionID' => 'change_sort', 'token' => $token)), 'title' => _("Clear Sort"))); } if ($mailbox->templates) { $a_view->templateedit = Horde::widget(array('url' => '#', 'class' => 'templateeditAction', 'title' => _("Edit Template"))); $mboxactions[] = Horde::widget(array('url' => $clink->copy()->add(array('actionID' => 'template_new')), 'title' => _("Create New Template"))); } $a_view->mboxactions = $mboxactions; if ($registry->hasMethod('mail/blacklistFrom')) { $a_view->blacklist = Horde::widget(array('url' => '#', 'class' => 'blacklistAction', 'title' => _("_Blacklist"))); } if ($registry->hasMethod('mail/whitelistFrom')) { $a_view->whitelist = Horde::widget(array('url' => '#', 'class' => 'whitelistAction', 'title' => _("_Whitelist"))); } if (IMP_Compose::canCompose()) { $a_view->forward = Horde::widget(array('url' => '#', 'class' => 'forwardAction', 'title' => _("Fo_rward"))); $a_view->redirect = Horde::widget(array('url' => '#', 'class' => 'redirectAction', 'title' => _("Redirect"))); } if ($mailbox->spam_show) { $a_view->spam = Horde::widget(array('url' => '#', 'class' => 'spamAction', 'title' => _("Report as Spam"))); } if ($mailbox->innocent_show) { $a_view->innocent = Horde::widget(array('url' => '#', 'class' => 'innocentAction', 'title' => _("Report as Innocent"))); } $a_view->view_messages = Horde::widget(array('url' => '#', 'class' => 'viewAction', 'title' => _("View Messages"))); $this->output .= $a_view->render('actions'); } /* Define some variables now so we don't have to keep redefining in * the foreach loop or the templates. */ $lastMbox = ''; $mh_count = 0; $sortImg = $sortpref->sortdir ? 'sortup' : 'sortdown'; $headers = array(Horde_Imap_Client::SORT_TO => array('id' => 'mboxto', 'stext' => _("Sort by To Address"), 'text' => _("To")), Horde_Imap_Client::SORT_FROM => array('id' => 'mboxfrom', 'stext' => _("Sort by From Address"), 'text' => _("Fro_m")), Horde_Imap_Client::SORT_THREAD => array('id' => 'mboxthread', 'stext' => _("Sort by Thread"), 'text' => _("_Thread")), Horde_Imap_Client::SORT_SUBJECT => array('id' => 'mboxsubject', 'stext' => _("Sort by Subject"), 'text' => _("Sub_ject")), IMP::IMAP_SORT_DATE => array('id' => 'mboxdate', 'stext' => _("Sort by Date"), 'text' => _("Dat_e")), Horde_Imap_Client::SORT_SIZE => array('id' => 'mboxsize', 'stext' => _("Sort by Message Size"), 'text' => _("Si_ze"))); /* If this is the Drafts or Sent-Mail mailbox, sort by To instead of * From. */ if ($mailbox->special_outgoing) { unset($headers[Horde_Imap_Client::SORT_FROM]); } else { unset($headers[Horde_Imap_Client::SORT_TO]); } /* Determine which of Subject/Thread to emphasize. */ if (!$mailbox->access_sortthread || $sortpref->sortby_locked) { unset($headers[Horde_Imap_Client::SORT_THREAD]); if ($sortpref->sortby_locked && $thread_sort) { $sortpref->sortby = Horde_Imap_Client::SORT_SUBJECT; } } else { if ($thread_sort) { $extra = Horde_Imap_Client::SORT_SUBJECT; $standard = Horde_Imap_Client::SORT_THREAD; } else { $extra = Horde_Imap_Client::SORT_THREAD; $standard = Horde_Imap_Client::SORT_SUBJECT; } $headers[$standard]['altsort'] = Horde::widget(array('url' => $mailbox_imp_url->copy()->add(array('actionID' => 'change_sort', 'token' => $token, 'sortby' => $extra)), 'title' => $headers[$extra]['text'])); unset($headers[$extra]); } foreach ($headers as $key => $val) { $ptr =& $headers[$key]; if ($sortpref->sortby == $key) { $csl_icon = '<span class="iconImg ' . $sortImg . '"></span>'; if ($sortpref->sortdir_locked) { $ptr['change_sort_link'] = $csl_icon; $ptr['change_sort_widget'] = Horde::stripAccessKey($val['text']); } else { $tmp = $mailbox_imp_url->copy()->add(array('sortby' => $key, 'sortdir' => intval(!$sortpref->sortdir), 'actionID' => 'change_sort', 'token' => $token)); $ptr['change_sort_link'] = Horde::link($tmp, $val['stext'], null, null, null, $val['stext']) . $csl_icon . '</a>'; $ptr['change_sort_widget'] = Horde::widget(array('url' => $tmp, 'title' => $val['text'])); } } else { $ptr['change_sort_link'] = null; $ptr['change_sort_widget'] = $sortpref->sortby_locked ? Horde::stripAccessKey($val['text']) : Horde::widget(array('url' => $mailbox_imp_url->copy()->add(array('actionID' => 'change_sort', 'token' => $token, 'sortby' => $key)), 'title' => $val['text'])); } $ptr['class'] = 'horde-split-left'; } /* Output the form start. */ $f_view = clone $view; $f_view->mailbox = $mailbox->form_to; $f_view->mailbox_url = $mailbox_url; $f_view->page = $pageOb['page']; $f_view->token = $token; $this->output .= $f_view->render('form_start'); /* Prepare the message headers template. */ $mh_view = clone $view; $mh_view->headers = $headers; if (!$search_mbox) { $mh_view->show_checkbox = !$mh_count++; $this->output .= $mh_view->render('message_headers'); } /* Initialize repetitively used variables. */ $fromlinkstyle = $prefs->getValue('from_link'); $imp_ui = new IMP_Mailbox_Ui($mailbox); /* Display message information. */ $msgs = array(); $search_view = clone $view; $summary_view = clone $view; while (list(, $ob) = each($mbox_info['overview'])) { if ($search_mbox) { if (empty($lastMbox) || $ob['mailbox'] != $lastMbox) { if (!empty($lastMbox)) { $this->_outputSummaries($msgs, $summary_view); $msgs = array(); } $mbox = IMP_Mailbox::get($ob['mailbox']); $search_view->mbox_link = Horde::link($mbox->url($mailbox_url), sprintf(_("View messages in %s"), $mbox->display), 'smallheader') . $mbox->display_html . '</a>'; $this->output .= $search_view->render('searchmbox'); $mh_view->show_checkbox = !$mh_count++; $this->output .= $mh_view->render('message_headers'); } } $lastMbox = $ob['mailbox']; /* Initialize the data fields. */ $msg = array('bg' => '', 'buid' => $imp_mailbox->getBuid($ob['mailbox'], $ob['uid']), 'class' => '', 'date' => $imp_ui->getDate($ob['envelope']->date), 'preview' => '', 'status' => '', 'size' => IMP::sizeFormat($ob['size'])); /* Generate the target link. */ if ($mailbox->drafts || $mailbox->templates) { $clink_copy = clone $clink_ob; $clink_copy->args['buid'] = $msg['buid']; $clink_copy->args['mailbox'] = $mailbox; $target = $clink_copy->link()->add(array('actionID' => $mailbox->drafts ? 'draft' : 'template')); } else { $target = $mailbox->url('message', $msg['buid']); } /* Get all the flag information. */ $flag_parse = $imp_flags->parse(array('flags' => $ob['flags'], 'headers' => $ob['headers'], 'runhook' => $ob, 'personal' => $ob['envelope']->to)); $css_class = $subject_flags = array(); foreach ($flag_parse as $val) { if ($val instanceof IMP_Flag_User) { $subject_flags[] = $val; } else { if (!$val->bgdefault) { $msg['bg'] = $val->bgcolor; } $css_class[] = $val->css; $msg['status'] .= $val->span; } } $msg['class'] = implode(' ', $css_class); /* Show message preview? */ if ($show_preview && isset($ob['preview'])) { if (empty($ob['preview'])) { $ptext = '[[' . _("No Preview Text") . ']]'; } else { $ptext = empty($strip_preview) ? str_replace("\r", '', $ob['preview']) : preg_replace(array('/\\n/', '/(\\s)+/'), array(' ', '$1'), str_replace("\r", "\n", $ob['preview'])); if (!$preview_tooltip) { $ptext = $injector->getInstance('Horde_Core_Factory_TextFilter')->filter($ptext, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::NOHTML)); } $maxlen = $prefs->getValue('preview_maxlen'); if (Horde_String::length($ptext) > $maxlen) { $ptext = Horde_String::truncate($ptext, $maxlen); } elseif (empty($ob['previewcut'])) { $ptext .= '[[' . _("END") . ']]'; } } $msg['preview'] = $ptext; } /* Format the From: Header. */ $getfrom = $imp_ui->getFrom($ob['envelope']); $msg['from'] = htmlspecialchars($getfrom['from'], ENT_QUOTES, 'UTF-8'); switch ($fromlinkstyle) { case 0: $from_tmp = array(); foreach ($getfrom['from_list']->base_addresses as $from_ob) { $from_tmp[] = call_user_func_array(array('Horde', $preview_tooltip ? 'linkTooltip' : 'link'), array($clink->copy()->add(array('actionID' => 'mailto_link', 'to' => strval($from_ob))), sprintf(_("New Message to %s"), $from_ob->label))) . htmlspecialchars($from_ob->label, ENT_QUOTES, 'UTF-8') . '</a>'; } if (!empty($from_tmp)) { $msg['from'] = implode(', ', $from_tmp); } break; default: $from_uri = $mailbox->url('message', $msg['buid']); $msg['from'] = Horde::link($from_uri) . $msg['from'] . '</a>'; break; } /* Format the Subject: Header. */ $msg['subject'] = $imp_ui->getSubject($ob['envelope']->subject, true); $msg['subject'] = $preview_tooltip ? substr(Horde::linkTooltip($target, $msg['preview'], '', '', '', $msg['preview']), 0, -1) . ' class="mboxSubject">' . $msg['subject'] . '</a>' : substr(Horde::link($target, $imp_ui->getSubject($ob['envelope']->subject)), 0, -1) . ' class="mboxSubject">' . $msg['subject'] . '</a>' . (!empty($msg['preview']) ? '<br /><small>' . $msg['preview'] . '</small>' : ''); /* Add subject flags. */ foreach ($subject_flags as $val) { $flag_label = Horde_String::truncate($val->label, 12); $msg['subject'] = '<span class="' . $val->css . '" style="' . ($val->bgdefault ? '' : 'background:' . htmlspecialchars($val->bgcolor) . ';') . 'color:' . htmlspecialchars($val->fgcolor) . '" title="' . htmlspecialchars($val->label) . '">' . htmlspecialchars($flag_label) . '</span>' . $msg['subject']; } /* Set up threading tree now. */ if ($thread_sort) { $t_ob = $imp_mailbox->getThreadOb($ob['idx']); $msg['subject'] = ($sortpref->sortdir ? $t_ob->reverse_img : $t_ob->img) . ' ' . $msg['subject']; } $msgs[$msg['buid']] = $msg; } $this->_outputSummaries($msgs, $summary_view); $this->output .= '</form>'; /* If there are 20 messages or less, don't show the actions/navbar * again. */ if ($pageOb['end'] - $pageOb['begin'] >= 20) { $this->output .= $a_view->render('actions'); $n_view->id = 2; $this->output .= $n_view->render('navbar'); } }
/** * Return the copy/move selection list. * * Variables used: NONE * * @return string HTML to use for the folder tree. */ public function copyMoveMailboxList() { $iterator = new IMP_Ftree_IteratorFilter($GLOBALS['injector']->getInstance('IMP_Ftree')); $iterator->add($iterator::REMOTE); return strval(new IMP_Ftree_Select(array('heading' => _("This message to"), 'iterator' => $iterator, 'optgroup' => true, 'inc_tasklists' => true, 'inc_notepads' => true, 'new_mbox' => true))); }
/** * AJAX action: Generate the sent-mail select list. * * Variables used: NONE * * @return object An object with the following properties: * - flist: (array) TODO */ public function sentMailList() { global $injector; /* Check to make sure the sent-mail mailboxes are created; they need * to exist to show up in drop-down list. */ $identity = $injector->getInstance('IMP_Identity'); foreach ($identity->getAllSentmail() as $mbox) { $mbox->create(); } $flist = array(); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add($iterator::NONIMAP); foreach ($iterator as $val) { $mbox_ob = $val->mbox_ob; $tmp = array('f' => $mbox_ob->display, 'l' => Horde_String::abbreviate(str_repeat(' ', 2 * $val->level) . $mbox_ob->basename, 30), 'v' => $val->container ? '' : $mbox_ob->form_to); if ($tmp['f'] == $tmp['v']) { unset($tmp['f']); } $flist[] = $tmp; } $ret = new stdClass(); $ret->flist = $flist; return $ret; }
/** * Add additional items to the sidebar. * * @param Horde_View_Sidebar $sidebar The sidebar object. */ public function sidebar($sidebar) { global $injector; if (IMP_Compose::canCompose()) { $clink = new IMP_Compose_Link(); $sidebar->addNewButton(_("_New Message"), $clink->link()); } /* Folders. */ if ($injector->getInstance('IMP_Factory_Imap')->create()->access(IMP_Imap::ACCESS_FOLDERS)) { try { $tree = $injector->getInstance('Horde_Core_Factory_Tree')->create('imp_menu', 'Horde_Tree_Renderer_Sidebar', array('nosession' => true)); $ftree = $injector->getInstance('IMP_Ftree'); $iterator = new IMP_Ftree_IteratorFilter($ftree); $iterator->add(array($iterator::REMOTE, $iterator::VFOLDER)); $tree = $ftree->createTree($tree, array('iterator' => $iterator, 'open' => false, 'poll_info' => true)); $sidebar->containers['imp-menu'] = array('content' => $tree->getTree()); } catch (Exception $e) { } } }
/** */ protected function _init() { global $injector, $notification, $page_output, $prefs, $registry, $session; /* Redirect back to the mailbox if folder use is not allowed. */ $imp_imap = $injector->getInstance('IMP_Factory_Imap')->create(); if (!$imp_imap->access(IMP_Imap::ACCESS_FOLDERS)) { $notification->push(_("The folder view is not enabled."), 'horde.error'); Horde::url('mailbox', true)->redirect(); } /* Decide whether or not to show all the unsubscribed mailboxes. */ $subscribe = $prefs->getValue('subscribe'); $showAll = !$subscribe || $session->get('imp', 'showunsub'); $page_output->addScriptFile('hordecore.js', 'horde'); $page_output->addScriptFile('folders.js'); /* Get the base URL for this page. */ $folders_url = self::url()->setRaw(true); /* These JS defines are required by all sub-pages. */ $page_output->addInlineJsVars(array('ImpFolders.folders_url' => strval($folders_url), 'ImpFolders.text' => array('download1' => _("All messages in the following mailbox(es) will be downloaded into one MBOX file:"), 'download2' => _("This may take some time. Are you sure you want to continue?"), 'oneselect' => _("Only one mailbox should be selected for this action."), 'rename1' => _("You are renaming the mailbox:"), 'rename2' => _("Please enter the new name:"), 'select' => _("Please select a mailbox before you perform this action."), 'subfolder1' => _("You are creating a subfolder to"), 'subfolder2' => _("Please enter the name of the new mailbox:"), 'toplevel' => _("You are creating a top-level mailbox.") . "\n" . _("Please enter the name of the new mailbox:")))); /* Initialize the IMP_Ftree object. */ $ftree = $injector->getInstance('IMP_Ftree'); /* $mbox_list entries are urlencoded. */ $mbox_list = isset($this->vars->mbox_list) ? IMP_Mailbox::formFrom($this->vars->mbox_list) : array(); /* META refresh time (might be altered by actionID). */ $refresh_time = $prefs->getValue('refresh_time'); /* Set up the master View object. */ $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/basic/folders')); $view->addHelper('FormTag'); $view->addHelper('Tag'); $token = $session->getToken(); $view->token = $token; /* Run through the action handlers. */ if ($this->vars->actionID) { try { $session->checkToken($this->vars->token); } catch (Horde_Exception $e) { $notification->push($e); $this->vars->actionID = null; } } switch ($this->vars->actionID) { case 'expand_all_folders': $ftree->expandAll(); break; case 'collapse_all_folders': $ftree->collapseAll(); break; case 'rebuild_tree': $ftree->init(); break; case 'expunge_mbox': if (!empty($mbox_list)) { $injector->getInstance('IMP_Message')->expungeMailbox(array_fill_keys($mbox_list, null)); } break; case 'delete_mbox': foreach ($mbox_list as $val) { $val->delete(); } break; case 'download_mbox': case 'download_mbox_zip': IMP_Contents_View::downloadUrl('mbox', array('actionID' => 'download_mbox', 'mbox_list' => $this->vars->mbox_list, 'type' => $this->vars->actionID == 'download_mbox' ? 'mbox' : 'mboxzip'))->redirect(); exit; case 'import_mbox': if ($this->vars->import_mbox) { try { $notification->push($injector->getInstance('IMP_Mbox_Import')->import($this->vars->import_mbox, 'mbox_upload'), 'horde.success'); } catch (Horde_Exception $e) { $notification->push($e); } $this->vars->actionID = null; } else { $refresh_time = null; } break; case 'create_mbox': if (isset($this->vars->new_mailbox)) { try { $parent = empty($mbox_list) ? IMP_Mailbox::get(IMP_Ftree::BASE_ELT) : $mbox_list[0]; $new_mbox = $parent->createMailboxName($this->vars->new_mailbox); if ($new_mbox->exists) { $notification->push(sprintf(_("Mailbox \"%s\" already exists."), $new_mbox->display), 'horde.warning'); } else { $new_mbox->create(); } } catch (Horde_Exception $e) { $notification->push($e); } } break; case 'rename_mbox': // $old_names may be URL encoded. $old_names = array_map('trim', explode("\n", $this->vars->old_names)); $new_names = array_map('trim', explode("\n", $this->vars->new_names)); $iMax = count($new_names); if (!empty($new_names) && !empty($old_names) && $iMax == count($old_names)) { for ($i = 0; $i < $iMax; ++$i) { $old_name = IMP_Mailbox::formFrom($old_names[$i]); $old_ns = $old_name->namespace_info; $new = trim($new_names[$i], $old_ns->delimiter); /* If this is a personal namespace, then anything goes as * far as the input. Just append the personal namespace to * it. */ if ($old_ns->type === $old_ns::NS_PERSONAL || strlen($old_ns->name) && stripos($new_names[$i], $old_ns->name) !== 0) { $new = $old_ns->name . $new; } $old_name->rename($new); } } break; case 'subscribe_mbox': case 'unsubscribe_mbox': if (empty($mbox_list)) { $notification->push(_("No mailboxes were specified"), 'horde.message'); } else { foreach ($mbox_list as $val) { $val->subscribe($this->vars->actionID == 'subscribe_mbox'); } } break; case 'toggle_subscribed_view': if ($subscribe) { $showAll = !$showAll; $session->set('imp', 'showunsub', $showAll); } break; case 'poll_mbox': if (!empty($mbox_list)) { $ftree->poll->addPollList($mbox_list); } break; case 'nopoll_mbox': if (!empty($mbox_list)) { $ftree->poll->removePollList($mbox_list); } break; case 'empty_mbox': if (!empty($mbox_list)) { $injector->getInstance('IMP_Message')->emptyMailbox($mbox_list); } break; case 'mark_mbox_seen': case 'mark_mbox_unseen': if (!empty($mbox_list)) { $injector->getInstance('IMP_Message')->flagAllInMailbox(array('\\seen'), $mbox_list, $this->vars->actionID == 'mark_mbox_seen'); } break; case 'delete_mbox_confirm': case 'empty_mbox_confirm': if (!empty($mbox_list)) { $loop = array(); foreach ($mbox_list as $val) { switch ($this->vars->actionID) { case 'delete_mbox_confirm': if (!$val->access_deletembox) { $notification->push(sprintf(_("The mailbox \"%s\" may not be deleted."), $val->display), 'horde.error'); continue 2; } break; case 'empty_mbox_confirm': if (!$val->access_empty) { $notification->push(sprintf(_("The mailbox \"%s\" may not be emptied."), $val->display), 'horde.error'); continue 2; } break; } try { $elt_info = $imp_imap->status($val, Horde_Imap_Client::STATUS_MESSAGES); } catch (IMP_Imap_Exception $e) { $elt_info = null; } $data = array('name' => $val->display, 'msgs' => $elt_info ? $elt_info['messages'] : 0, 'val' => $val->form_to); $loop[] = $data; } if (!count($loop)) { break; } $page_output->addScriptFile('stripe.js', 'horde'); $this->title = _("Folder Actions - Confirmation"); $v = clone $view; if ($this->vars->actionID == 'delete_mbox_confirm') { $v->actionID = 'delete_mbox'; $v->delete = true; } elseif ($this->vars->actionID == 'empty_mbox_confirm') { $v->actionID = 'empty_mbox'; $v->empty = true; } $v->mboxes = $loop; $v->folders_url = $folders_url; $this->output = $v->render('folders_confirm'); return; } break; case 'mbox_size': if (!empty($mbox_list)) { $loop = array(); $sum = 0; foreach ($mbox_list as $val) { $size = $val->size; $data = array('name' => $val->display, 'size' => sprintf(_("%.2fMB"), $size / (1024 * 1024)), 'sort' => $size); $sum += $size; $loop[] = $data; } /* Prepare the topbar. */ $injector->getInstance('Horde_View_Topbar')->subinfo = $injector->getInstance('IMP_View_Subinfo')->render(); $v = clone $view; $v->folders_url = $folders_url; $v->mboxes = $loop; $v->mboxes_sum = sprintf(_("%.2fMB"), $sum / (1024 * 1024)); $page_output->addScriptFile('stripe.js', 'horde'); $page_output->addScriptFile('tables.js', 'horde'); $this->title = _("Mailbox Sizes"); $this->output = $v->render('folders_size'); return; } break; case 'search': if (!empty($mbox_list)) { IMP_Basic_Search::url()->add(array('mailbox_list' => IMP_Mailbox::formTo($mbox_list), 'subfolder' => 1))->redirect(); } break; } $this->title = _("Folder Navigator"); $folders_url->add('token', $token); /* Prepare the topbar. */ $injector->getInstance('Horde_View_Topbar')->subinfo = $injector->getInstance('IMP_View_Subinfo')->render(); if ($session->get('imp', 'file_upload') && $this->vars->actionID == 'import_mbox') { /* Prepare import template. */ $v = clone $view; $v->folders_url = $folders_url; $v->import_mbox = $mbox_list[0]; $this->output = $v->render('import'); return; } /* Prepare the header template. */ $head_view = clone $view; $head_view->folders_url = $folders_url; /* Prepare the actions template. */ $actions = clone $view; $actions->addHelper('Horde_Core_View_Helper_Accesskey'); $actions->addHelper('Horde_Core_View_Helper_Help'); $actions->id = 0; $actions->refresh = Horde::widget(array('title' => _("_Refresh"), 'url' => $folders_url->copy())); $actions->create_mbox = $imp_imap->access(IMP_Imap::ACCESS_CREATEMBOX) && $imp_imap->access(IMP_Imap::ACCESS_CREATEMBOX_MAX); if ($prefs->getValue('subscribe')) { $actions->subscribe = true; $subToggleText = $showAll ? _("Hide Unsubscribed") : _("Show All"); $actions->toggle_subscribe = Horde::widget(array('url' => $folders_url->copy()->add(array('actionID' => 'toggle_subscribed_view', 'token' => $token)), 'title' => $subToggleText, 'nocheck' => true)); } $actions->nav_poll = !$prefs->isLocked('nav_poll') && !$prefs->getValue('nav_poll_all'); $actions->notrash = !$prefs->getValue('use_trash'); $actions->file_upload = $session->get('imp', 'file_upload'); $actions->expand_all = Horde::widget(array('url' => $folders_url->copy()->add(array('actionID' => 'expand_all_folders', 'token' => $token)), 'title' => _("Expand All"), 'nocheck' => true)); $actions->collapse_all = Horde::widget(array('url' => $folders_url->copy()->add(array('actionID' => 'collapse_all_folders', 'token' => $token)), 'title' => _("Collapse All"), 'nocheck' => true)); /* Build the folder tree. */ $iterator = new IMP_Ftree_IteratorFilter($ftree); $iterator->add(array($iterator::REMOTE, $iterator::VFOLDER)); if ($showAll) { $ftree->loadUnsubscribed(); $iterator->remove($iterator::UNSUB); } $tree = $ftree->createTree('imp_folders', array('checkbox' => true, 'editvfolder' => true, 'iterator' => $iterator, 'poll_info' => true)); $displayNames = $fullNames = array(); foreach ($ftree as $val) { $mbox_ob = $val->mbox_ob; $tmp = $displayNames[] = $mbox_ob->display; $tmp2 = $mbox_ob->display_notranslate; if ($tmp != $tmp2) { $fullNames[strval($val)] = $tmp2; } } $page_output->addInlineJsVars(array('ImpFolders.ajax' => $registry->getServiceLink('ajax', 'imp')->url, 'ImpFolders.displayNames' => $displayNames, 'ImpFolders.fullNames' => $fullNames, '-ImpFolders.mbox_expand' => intval($prefs->getValue('nav_expanded') == 2))); $page_output->metaRefresh($refresh_time, $this->url()); Horde::startBuffer(); $tree->renderTree(); $this->output = $head_view->render('head') . $actions->render('actions') . Horde::endBuffer(); if (count($tree) > 10) { $actions->id = 1; $this->output .= $actions->render('actions'); } /* No need for extra template - close out the tags here. */ $this->output .= '</form>'; }
/** * Returns the list of mailboxes. * * @param array $opts Additional options: * <pre> * - unsub: (boolean) If true, return unsubscribed mailboxes. * </pre> * * @return array The list of IMAP mailboxes. A list of arrays with the * following keys: * <pre> * - d: (string) The namespace delimiter. * - label: (string) Human readable label (UTF-8). * - level: (integer) The child level of this element. * - ob: (Horde_Imap_Client_Mailbox) A mailbox object. * - subscribed: (boolean) True if mailbox is subscribed. * </pre> */ public function mailboxList(array $opts = array()) { global $injector; $ftree = $injector->getInstance('IMP_Ftree'); if (!empty($opts['unsub'])) { /* Make sure unsubscribed mailboxes are loaded. */ $ftree->loadUnsubscribed(); } $iterator = new IMP_Ftree_IteratorFilter($ftree); $iterator->add(array($iterator::CONTAINERS, $iterator::REMOTE, $iterator::VFOLDER)); if (!empty($opts['unsub'])) { $iterator->remove($iterator::UNSUB); } $mboxes = array(); foreach ($iterator as $val) { $mbox_ob = $val->mbox_ob; $sub = $mbox_ob->sub; $mboxes[] = array('d' => $mbox_ob->namespace_delimiter, 'label' => $mbox_ob->label, 'level' => $val->level, 'ob' => $mbox_ob->imap_mbox_ob, 'subscribed' => $sub); } return $mboxes; }
/** * Return the number of mailboxes on the server. */ public function count() { $this->loadUnsubscribed(); $iterator = new IMP_Ftree_IteratorFilter($this); $iterator->add($iterator::NONIMAP); $iterator->remove($iterator::UNSUB); return iterator_count($iterator); }
/** */ public function __get($name) { global $injector; switch ($name) { case 'all': return in_array(self::ALLSEARCH, $this->_mboxes); case 'canEdit': return $this->_canEdit; case 'criteria': $out = array(); foreach ($this->_criteria as $elt) { $out[] = array('criteria' => $elt->getCriteria(), 'element' => get_class($elt)); } return $out; case 'formid': return $this->mbox_ob->form_to; case 'id': return $this->_id; case 'label': return $this->_label; case 'mboxes': if (!isset($this->_cache['mboxes'])) { $out = $this->mbox_list; if (!$this->all && ($s_list = $this->subfolder_list)) { foreach ($s_list as $val) { $out = array_merge($out, $val->subfolders); } } $this->_cache['mboxes'] = array_unique($out, SORT_REGULAR); } return $this->_cache['mboxes']; case 'mbox_list': case 'subfolder_list': if (!isset($this->_cache['mbox_list'])) { $mbox = $subfolder = array(); if ($this->all) { $mbox = array(); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add(array($iterator::CONTAINERS, $iterator::NONIMAP)); foreach ($iterator as $val) { $mbox[] = $val->mbox_ob; } } else { foreach ($this->_mboxes as $val) { if (strpos($val, self::SUBFOLDER) === 0) { $subfolder[] = IMP_Mailbox::get(substr($val, strlen(self::SUBFOLDER))); } else { $mbox[] = IMP_Mailbox::get($val); } } } $this->_cache['mbox_list'] = $mbox; $this->_cache['subfolder_list'] = $subfolder; } return $this->_cache[$name]; case 'mbox_ob': return IMP_Mailbox::get($this->mid); case 'mid': return IMP_Search::MBOX_PREFIX . $this->_id; case 'query': $qout = array(); foreach ($this->mboxes as $mbox) { if ($mbox->container) { continue; } $query = new Horde_Imap_Client_Search_Query(); foreach ($this->_criteria as $elt) { $query = $elt->createQuery($mbox, $query); } $qout[strval($mbox)] = $query; } return $qout; case 'querytext': $text = array(); foreach ($this->_criteria as $elt) { if ($elt instanceof IMP_Search_Element_Or) { array_pop($text); $text[] = $elt->queryText(); } else { $text[] = $elt->queryText(); $text[] = _("and"); } } array_pop($text); $mbox_display = array(); if ($this->all) { $mbox_display[] = _("All Mailboxes"); } else { foreach ($this->mboxes as $val) { $mbox_display[] = $val->display; } } return sprintf(_("Search %s in %s"), implode(' ', $text), '[' . implode(', ', $mbox_display) . ']'); } }
/** */ public function display(Horde_Core_Prefs_Ui $ui) { global $injector, $notification, $page_output; $page_output->addScriptFile('acl.js'); $acl = $injector->getInstance('IMP_Imap_Acl'); $mbox = isset($ui->vars->mbox) ? IMP_Mailbox::formFrom($ui->vars->mbox) : IMP_Mailbox::get('INBOX'); try { $curr_acl = $acl->getACL($mbox); if (!($canEdit = $acl->canEdit($mbox))) { $notification->push(_("You do not have permission to change access to this mailbox."), 'horde.warning'); } } catch (IMP_Exception $e) { $notification->push($e); $canEdit = false; $curr_acl = array(); } $rightslist = $acl->getRights(); $iterator = new IMP_Ftree_IteratorFilter($injector->getInstance('IMP_Ftree')); $iterator->add($iterator::NONIMAP); $view = new Horde_View(array('templatePath' => IMP_TEMPLATES . '/prefs')); $view->addHelper('FormTag'); $view->addHelper('Tag'); $view->addHelper('Text'); $view->canedit = $canEdit; $view->current = sprintf(_("Current access to %s"), $mbox->display_html); $view->hasacl = count($curr_acl); $view->mbox = $mbox->form_to; $view->options = new IMP_Ftree_Select(array('basename' => true, 'iterator' => $iterator, 'selected' => $mbox)); if ($view->hasacl) { $cval = array(); foreach ($curr_acl as $index => $rule) { $entry = array('index' => $index, 'rule' => array()); if ($rule instanceof Horde_Imap_Client_Data_AclNegative) { $entry['negative'] = substr($index, 1); } /* Create table of each ACL option for each user granted * permissions; enabled indicates the right has been given to * the user. */ $rightsmbox = $acl->getRightsMbox($mbox, $index); foreach (array_keys($rightslist) as $val) { $entry['rule'][] = array('disable' => !$canEdit || !$rightsmbox[$val], 'on' => $rule[$val], 'val' => $val); } $cval[] = $entry; } $view->curr_acl = $cval; } $current_users = array_keys($curr_acl); $new_user = array(); try { $auth_imap = $injector->getInstance('IMP_AuthImap'); foreach (array('anyone') + $auth_imap->listUsers() as $user) { if (!in_array($user, $current_users)) { $new_user[] = htmlspecialchars($user); } } $view->new_user = $new_user; } catch (IMP_Exception $e) { /* Ignore - admin user is not available. */ } catch (Horde_Exception $e) { $notification->push('Could not authenticate as admin user to obtain ACLs. Perhaps your admin configuration is incorrect in config/backends.local.php?', 'horde.warning'); } $rights = array(); foreach ($rightslist as $key => $val) { $val['val'] = $key; $rights[] = $val; } $view->rights = $rights; $view->width = round(100 / (count($rights) + 2)) . '%'; return $view->render('acl'); }
/** */ 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_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 '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'; } 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, 'basename' => true, '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'); } }