Files
server/usr/share/psa-horde/imp/lib/Ajax/Application.php
2026-01-07 20:52:11 +01:00

385 lines
12 KiB
PHP

<?php
/**
* Copyright 2010-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (GPL). If you
* did not receive this file, see http://www.horde.org/licenses/gpl.
*
* @category Horde
* @copyright 2010-2017 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/
/**
* Defines the AJAX interface for IMP.
*
* Global tasks:
* - msgload: (string) BUID of a message to load in the background (mailbox
* is located in 'mailbox' parameter).
* - poll: (string) The list of mailboxes to process (JSON encoded
* array; mailboxes are base64url encoded). If an empty array, polls
* all mailboxes.
*
* Global parameters (in viewport parameter):
* - force: (integer) If set, always return viewport information if changed.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2010-2017 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/
class IMP_Ajax_Application extends Horde_Core_Ajax_Application
{
/**
* The IMP_Indices_Mailbox object based on form data.
*
* @var IMP_Indices_Mailbox
*/
public $indices;
/**
* Queue object.
*
* @var IMP_Ajax_Queue
*/
public $queue;
/**
*/
protected function _init()
{
global $injector, $registry;
$this->queue = $injector->getInstance('IMP_Ajax_Queue');
switch ($registry->getView()) {
case $registry::VIEW_BASIC:
$this->addHandler('IMP_Ajax_Application_Handler_Mboxtoggle');
$this->addHandler('IMP_Ajax_Application_Handler_Passphrase');
$this->addHandler('IMP_Ajax_Application_Handler_Search');
if ($injector->getInstance('IMP_Factory_Imap')->create()->access(IMP_Imap::ACCESS_REMOTE)) {
$this->addHandler('IMP_Ajax_Application_Handler_RemotePrefs');
}
break;
case $registry::VIEW_DYNAMIC:
$this->addHandler('IMP_Ajax_Application_Handler_Common');
$this->addHandler('IMP_Ajax_Application_Handler_ComposeAttach');
$this->addHandler('IMP_Ajax_Application_Handler_Draft');
$this->addHandler('IMP_Ajax_Application_Handler_Dynamic');
$this->addHandler('IMP_Ajax_Application_Handler_Mboxtoggle');
$this->addHandler('IMP_Ajax_Application_Handler_Passphrase');
$this->addHandler('IMP_Ajax_Application_Handler_Search');
if ($injector->getInstance('IMP_Factory_Imap')->create()->access(IMP_Imap::ACCESS_REMOTE)) {
$this->addHandler('IMP_Ajax_Application_Handler_Remote');
$this->addHandler('IMP_Ajax_Application_Handler_RemotePrefs');
}
break;
case $registry::VIEW_SMARTMOBILE:
$this->addHandler('IMP_Ajax_Application_Handler_Common');
$this->addHandler('IMP_Ajax_Application_Handler_ComposeAttach');
$this->addHandler('IMP_Ajax_Application_Handler_Draft')->disabled = array(
'autoSaveDraft',
'saveTemplate'
);
$this->addHandler('IMP_Ajax_Application_Handler_Smartmobile');
break;
}
$this->addHandler('IMP_Ajax_Application_Handler_ImageUnblock');
$this->addHandler('Horde_Core_Ajax_Application_Handler_Imple');
$this->addHandler('Horde_Core_Ajax_Application_Handler_Prefs');
/* Copy 'view' paramter to 'mailbox', because this is what
* IMP_Indices_Mailbox expects. */
if (isset($this->_vars->view)) {
$this->_vars->mailbox = $this->_vars->view;
}
$this->indices = new IMP_Indices_Mailbox($this->_vars);
/* Make sure the viewport entry is initialized. */
$vp = isset($this->_vars->viewport)
? json_decode($this->_vars->viewport)
: new stdClass;
$this->_vars->viewport = new Horde_Support_ObjectStub($vp);
/* GLOBAL TASKS */
/* Check for global msgload task. */
if (isset($this->_vars->msgload)) {
$this->queue->message($this->indices->mailbox->fromBuids(array($this->_vars->msgload)), true, true);
}
/* Check for global poll task. */
if (isset($this->_vars->poll)) {
$poll = json_decode($this->_vars->poll);
$this->queue->poll(
empty($poll)
? $injector->getInstance('IMP_Ftree')->poll->getPollList()
: IMP_Mailbox::formFrom($poll),
true
);
}
}
/**
*/
public function send()
{
$this->getTasks();
parent::send();
}
/**
* Get the list of tasks.
*
* @return array Task list.
*/
public function getTasks()
{
$this->queue->add($this);
/* Convert viewport to output format. */
$name = 'imp:viewport';
if (isset($this->tasks->$name)) {
$this->tasks->$name = $this->tasks->$name->toObject();
}
return $this->tasks;
}
/* Shared code between handlers. */
/**
* Initialize the objects needed to compose.
*
* @return object Object with the following properties:
* - ajax: IMP_Ajax_Application_Compose object
* - compose: IMP_Compose object
* - contents: IMP_Contents object
*/
public function initCompose()
{
global $injector;
$ob = new stdClass;
$ob->compose = $injector->getInstance('IMP_Factory_Compose')->create($this->_vars->imp_compose);
$ob->ajax = new IMP_Ajax_Application_Compose($ob->compose, $this->_vars->type);
if (!($ob->contents = $ob->compose->getContentsOb()) &&
count($this->indices)) {
$ob->contents = $injector->getInstance('IMP_Factory_Contents')->create($this->indices);
}
$this->queue->compose($ob->compose);
return $ob;
}
/**
* Check the UID validity of the mailbox.
*
* See the list of variables needed for viewPortData().
*/
public function checkUidvalidity()
{
try {
$this->indices->mailbox->uidvalid;
} catch (IMP_Exception $e) {
$this->addTask('viewport', $this->viewPortData(true));
}
}
/**
* Generate the information necessary for a ViewPort request from/to the
* browser.
*
* Variables used (contained in 'viewport' object):
* - applyfilter
* - cache
* - cacheid
* - delhide
* - initial
* - qsearch
* - qsearchfield
* - qsearchfilter
* - qsearchflag
* - qsearchflagnot
* - qsearchmbox
* - rangeslice
* - sortby
* - sortdir
*
* @param boolean $change True if cache information has changed.
*
* @return IMP_Ajax_Application_Viewport Viewport data object.
*/
public function viewPortData($change)
{
$args = array(
'change' => $change,
'mbox' => strval($this->indices->mailbox)
);
$params = array(
'applyfilter', 'cache', 'cacheid', 'delhide', 'initial', 'qsearch',
'qsearchfield', 'qsearchfilter', 'qsearchflag', 'qsearchflagnot',
'qsearchmbox', 'rangeslice', 'sortby', 'sortdir'
);
$vp = $this->_vars->viewport;
foreach ($params as $val) {
$args[$val] = $vp->$val;
}
if ($vp->search || $args['initial']) {
$args += array(
'after' => intval($vp->after),
'before' => intval($vp->before)
);
}
if ($vp->search) {
$search = json_decode($vp->search);
$args += array(
'search_buid' => isset($search->buid) ? $search->buid : null,
'search_unseen' => isset($search->unseen) ? $search->unseen : null
);
} else {
list($slice_start, $slice_end) = explode(':', $vp->slice, 2);
$args += array(
'slice_start' => intval($slice_start),
'slice_end' => intval($slice_end)
);
}
return $GLOBALS['injector']->getInstance('IMP_Ajax_Application_ListMessages')->listMessages($args);
}
/**
* Determine if the cache information has changed.
*
* Variables used:
* - cacheid: (string) The browser (ViewPort) cache identifier.
* - forceUpdate: (integer) If 1, forces an update.
*
* @param boolean $rw Open mailbox as READ+WRITE?
*
* @return boolean True if the server state differs from the browser
* state.
*/
public function changed($rw = null)
{
/* Forced viewport return. */
if ($this->_vars->viewport->force) {
return true;
}
/* Only update search mailboxes on forced refreshes. */
if ($this->indices->mailbox->search) {
return !empty($this->_vars->forceUpdate);
}
if (!$this->_vars->viewport->cacheid) {
return false;
}
/* We know we are going to be dealing with this mailbox, so select it
* on the IMAP server (saves some STATUS calls). */
if (!is_null($rw)) {
try {
$this->indices->mailbox->imp_imap->openMailbox($this->indices->mailbox, $rw ? Horde_Imap_Client::OPEN_READWRITE : Horde_Imap_Client::OPEN_AUTO);
} catch (IMP_Imap_Exception $e) {
$e->notify();
return null;
}
}
return ($this->indices->mailbox->cacheid_date != $this->_vars->viewport->cacheid);
}
/**
* Setup environment for compose actions.
*
* Variables used:
* - composeCache: (string) The IMP_Compose cache identifier.
* - from: (string) From address to use.
* - identity: (integer) The identity to use
*
* @param string $action AJAX action.
*
* @return array An array with the following values:
* - (object) AJAX base return object (with action and success
* parameters defined).
* - (IMP_Compose) The IMP_Compose object for the message.
* - (array) The list of headers for the object.
* - (Horde_Prefs_Identity) The identity used for the composition.
*
* @throws Horde_Exception
*/
public function composeSetup($action)
{
global $injector, $prefs;
/* Set up identity. */
$identity = $injector->getInstance('IMP_Identity');
if (isset($this->_vars->identity) &&
!$prefs->isLocked('default_identity')) {
$identity->setDefault($this->_vars->identity);
}
/* Set up the From address based on the identity. */
$headers = array(
'from' => strval($identity->getFromLine(null, $this->_vars->from)),
'to' => $this->_vars->to,
'cc' => $this->_vars->cc,
'bcc' => $this->_vars->bcc,
'subject' => $this->_vars->subject
);
$imp_compose = $injector->getInstance('IMP_Factory_Compose')->create($this->_vars->composeCache);
$result = new stdClass;
$result->action = $action;
$result->success = 1;
return array($result, $imp_compose, $headers, $identity);
}
/**
* Processes delete message requests.
* See the list of variables needed for viewPortData().
*
* @param IMP_Indices $indices An indices object.
* @param boolean $changed If true, add full ViewPort information.
* @param boolean $force If true, forces addition of disappear
* information.
*/
public function deleteMsgs(IMP_Indices $indices, $changed, $force = false)
{
/* Check if we need to update thread information. */
if (!$changed) {
$changed = ($this->indices->mailbox->getSort()->sortby == Horde_Imap_Client::SORT_THREAD);
}
if ($changed) {
$vp = $this->viewPortData(true);
$this->addTask('viewport', $vp);
} elseif (($indices instanceof IMP_Indices_Mailbox) &&
($force || $this->indices->mailbox->hideDeletedMsgs(true))) {
$vp = new IMP_Ajax_Application_Viewport($this->indices->mailbox);
$vp->disappear = $indices->buids[strval($this->indices->mailbox)];
$this->addTask('viewport', $vp);
}
$this->queue->poll(array_keys($indices->indices()));
}
}