--- /dev/null
+<?php
+/**
+ * Perform AJAX actions.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @package Horde_Ajax
+ */
+class Horde_Ajax
+{
+ /**
+ * Get a Horde_Ajax_Application_Base instance.
+ *
+ * @param string $app The application name.
+ * @param string $action The AJAX action to perform.
+ *
+ * @return Horde_Ajax_Application_Base The requested instance.
+ * @throws Horde_Exception
+ */
+ static public function getInstance($app, $action = null)
+ {
+ $class = $app . '_Ajax_Application';
+
+ if (class_exists($class)) {
+ return new $class($action);
+ }
+
+ throw new Horde_Ajax_Exception('Ajax configuration for ' . $app . ' not found.');
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Defines the AJAX interface for an application.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @package Horde_Ajax
+ */
+abstract class Horde_Ajax_Application_Base
+{
+ /**
+ * The action to perform.
+ *
+ * @var string
+ */
+ protected $_action;
+
+ /**
+ * The list of actions that require readonly access to the session.
+ *
+ * @var array
+ */
+ protected $_readOnly = array();
+
+ /**
+ * Constructor.
+ *
+ * @param string $action The AJAX action to perform.
+ */
+ public function __construct($action = null)
+ {
+ if (!is_null($action)) {
+ /* Close session if action is labeled as read-only. */
+ if (in_array($action, $this->_readOnly)) {
+ session_write_close();
+ }
+
+ $this->_action = $action;
+ }
+ }
+
+ /**
+ * Performs the AJAX action.
+ *
+ * @return mixed The result of the action call.
+ * @throws Horde_Ajax_Exception
+ */
+ public function doAction()
+ {
+ if (!$this->_action) {
+ return false;
+ }
+
+ if (method_exists($this, $this->_action)) {
+ return call_user_func(array($this, $this->_action), Horde_Variables::getDefaultVariables());
+ }
+
+ throw new Horde_Ajax_Exception('Handler for action "' . $this->_action . '" does not exist.');
+ }
+
+ /**
+ * Returns a notification handler object to use to output any
+ * notification messages triggered by the AJAX action.
+ *
+ * @return Horde_Notification_Handler_Base The notification handler.
+ */
+ public function notificationHandler()
+ {
+ return null;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Exception object for the Horde_Ajax package.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @package Horde_Ajax
+ */
+class Horde_Ajax_Exception extends Horde_Exception
+{
+}
<api>beta</api>
</stability>
<license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
- <notes>* Add AutoCompleter driver.
+ <notes>* Add Application framework.
+ * Add AutoCompleter driver.
* Initial release.
</notes>
<contents>
<dir name="lib">
<dir name="Horde">
<dir name="Ajax">
+ <dir name="Application">
+ <file name="Base.php" role="php" />
+ </dir> <!-- /lib/Horde/Ajax/Application -->
<dir name="Imple">
<file name="AutoCompleter.php" role="php" />
<file name="Base.php" role="php" />
<file name="Geonames.php" role="php" />
</dir>
</dir> <!-- /lib/Horde/Ajax/Imple -->
+ <file name="Exception.php" role="php" />
<file name="Imple.php" role="php" />
</dir> <!-- /lib/Horde/Ajax -->
+ <file name="Ajax.php" role="php" />
</dir> <!-- /lib/Horde -->
</dir> <!-- /lib -->
</dir> <!-- / -->
<name>Core</name>
<channel>pear.horde.org</channel>
</package>
+ <package>
+ <name>Util</name>
+ <channel>pear.horde.org</channel>
+ </package>
</required>
<optional>
<package>
</dependencies>
<phprelease>
<filelist>
+ <install name="lib/Horde/Ajax/Application/Base.php" as="Horde/Ajax/Application/Base.php" />
+ <install name="lib/Horde/Ajax/Exception.php" as="Horde/Ajax/Exception.php" />
<install name="lib/Horde/Ajax/Imple/AutoCompleter.php" as="Horde/Ajax/Imple/AutoCompleter.php" />
<install name="lib/Horde/Ajax/Imple/Base.php" as="Horde/Ajax/Imple/Base.php" />
<install name="lib/Horde/Ajax/Imple/SpellChecker.php" as="Horde/Ajax/Imple/SpellChecker.php" />
<install name="lib/Horde/Ajax/Imple.php" as="Horde/Ajax/Imple.php" />
<install name="lib/Horde/Ajax/Imple/Geocoder/Geonames.php" as="Horde/Ajax/Imple/Geocoder/Geonames.php" />
+ <install name="lib/Horde/Ajax.php" as="Horde/Ajax.php" />
</filelist>
</phprelease>
<changelog/>
*
* The following are service links only and do not need to be defined
* in Horde's menu config.
- * 'cache', 'download', 'go', 'prefsapi'
+ * 'ajax', 'cache', 'download', 'go', 'prefsapi'
* </pre>
* @param string $app The name of the current Horde application.
* @param boolean $override Override Horde settings?
*/
static public function getServiceLink($type, $app, $override = false)
{
- if (!in_array($type, array('cache', 'download', 'go', 'prefsapi')) &&
+ if (!in_array($type, array('ajax', 'cache', 'download', 'go', 'prefsapi')) &&
!self::showService($type, $override)) {
return false;
}
case 'go':
return self::url($webroot . '/services/go.php');
+
+ case 'ajax':
+ return self::url($webroot . '/services/ajax.php/' . $app . '/');
}
return false;
public $applications = array();
/**
- * Application initialization (called from within an application).
+ * Application bootstrap initialization.
* Solves chicken-and-egg problem - need a way to init Horde environment
* from application without an active Horde_Registry object.
*
- * Page compression will be started (if configured) via this function.
+ * Page compression will be started (if configured).
+ * init() will be called after the initialization is completed.
*
* Global variables defined:
* $registry - Registry object
v4.0-cvs
--------
+[mms] Add abstracted AJAX interface (Requesst #4561).
[cjh] Cast Horde_Url objects to strings in Horde_Tree.
[mms] Update scriptaculous to v1.8.3.
[mjr] Add Horde_Image_Exif (ported from Ansel) and add a exiftool driver.
--- /dev/null
+<?php
+/**
+ * Processes an AJAX request and returns a JSON encoded result.
+ *
+ * Path Info:
+ * ----------
+ * http://example.com/horde/services/ajax.php/APP/ACTION
+ *
+ * 'APP' - (string) The application name.
+ * 'ACTION' - (string) The AJAX action identifier.
+ *
+ * Reserved 'ACTION' strings:
+ * 'LogOut' - Logs user out of Horde.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @package Horde
+ */
+
+require_once dirname(__FILE__) . '/../lib/Application.php';
+
+list($app, $action) = explode('/', trim(Horde_Util::getPathInfo(), '/'));
+if (empty($action)) {
+ // This is the only case where we really don't return anything, since
+ // the frontend can be presumed not to make this request on purpose.
+ // Other missing data cases we return a response of boolean false.
+ exit;
+}
+
+try {
+ Horde_Registry::appInit($app, array('authentication' => 'throw'));
+} catch (Horde_Exception $e) {
+ /* Handle session timeouts when they come from an AJAX request. */
+ if (($e->getCode() == Horde_Registry::AUTH_FAILURE) &&
+ ($action != 'LogOut')) {
+ $ajax = Horde_Ajax::getInstance($app);
+ $notification = Horde_Notification::singleton();
+
+ $notification->push(str_replace('&', '&', Horde_Auth::getLogoutUrl(array('reason' => Horde_Auth::REASON_SESSION))), 'horde.ajaxtimeout', array('content.raw'));
+ Horde::sendHTTPResponse(Horde::prepareResponse(null, $ajax->notificationHandler()), 'json');
+ exit;
+ }
+
+ Horde_Auth::authenticateFailure($app, $e);
+}
+
+// Handle logout requests. This needs to be done here, rather than on the
+// browser, because the logout tokens might otherwise expire.
+if ($action == 'LogOut') {
+ Horde::redirect(str_replace('&', '&', Horde::getServiceLink('logout', $app)));
+ exit;
+}
+
+// Open an output buffer to ensure that we catch errors that might break JSON
+// encoding.
+ob_start();
+
+$ajax = Horde_Ajax::getInstance($app, $action);
+$result = $ajax->doAction();
+
+// Clear the output buffer that we started above, and log any unexpected
+// output at a DEBUG level.
+if (ob_get_length()) {
+ Horde::logMessage('Unexpected output (' . $app . '): ' . ob_get_clean(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+}
+
+// Send the final result.
+Horde::sendHTTPResponse(Horde::prepareResponse($result, $ajax->notificationHandler()), 'json');
+++ /dev/null
-<?php
-/**
- * Performs the AJAX-requested action.
- *
- * Copyright 2005-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author Michael Slusarz <slusarz@horde.org>
- * @package IMP
- */
-
-function _generateDeleteResult($mbox, $indices, $change, $nothread = false)
-{
- $imp_mailbox = IMP_Mailbox::singleton($mbox);
-
- $del = new stdClass;
- $del->folder = $mbox;
- $del->uids = $GLOBALS['imp_imap']->ob()->utils->toSequenceString($indices, array('mailbox' => true));
- $del->remove = intval($GLOBALS['prefs']->getValue('hide_deleted') ||
- $GLOBALS['prefs']->getValue('use_trash'));
- $del->cacheid = $imp_mailbox->getCacheID($mbox);
-
- $result = new stdClass;
- $result->deleted = $del;
-
- /* Check if we need to update thread information. */
- if (!$change && !$nothread) {
- $sort = IMP::getSort($mbox);
- $change = ($sort['by'] == Horde_Imap_Client::SORT_THREAD);
- }
-
- if ($change) {
- $result->ViewPort = _getListMessages($mbox, true);
- }
-
- $poll = _getPollInformation($mbox);
- if (!empty($poll)) {
- $result->poll = $poll;
- }
-
- return $result;
-}
-
-function _changed($mbox, $compare, $action, $rw = null)
-{
- /* Only update search mailboxes on forced refreshes. */
- if ($GLOBALS['imp_search']->isSearchMbox($mbox)) {
- return ($action == 'ViewPort') || Horde_Util::getPost('forceUpdate');
- }
-
- /* 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) && !$GLOBALS['imp_search']->isSearchMbox($mbox)) {
- try {
- $GLOBALS['imp_imap']->ob()->openMailbox($mbox, $rw ? Horde_Imap_Client::OPEN_READWRITE : Horde_Imap_Client::OPEN_AUTO);
- } catch (Horde_Imap_Client_Exception $e) {
- $GLOBALS['notification']->push($e, 'horde.error');
- return null;
- }
- }
-
- $imp_mailbox = IMP_Mailbox::singleton($mbox);
- return ($imp_mailbox->getCacheID($mbox) != $compare);
-}
-
-function _getListMessages($mbox, $change)
-{
- $args = array(
- 'applyfilter' => Horde_Util::getPost('applyfilter'),
- 'cache' => Horde_Util::getPost('cache'),
- 'cacheid' => Horde_Util::getPost('cacheid'),
- 'change' => $change,
- 'initial' => Horde_Util::getPost('initial'),
- 'mbox' => $mbox,
- 'rangeslice' => Horde_Util::getPost('rangeslice'),
- 'requestid' => Horde_Util::getPost('requestid'),
- 'qsearch' => Horde_Util::getPost('qsearch'),
- 'qsearchflag' => Horde_Util::getPost('qsearchflag'),
- 'qsearchmbox' => Horde_Util::getPost('qsearchmbox'),
- 'qsearchflagnot' => Horde_Util::getPost('qsearchflagnot'),
- 'sortby' => Horde_Util::getPost('sortby'),
- 'sortdir' => Horde_Util::getPost('sortdir'),
- );
-
- $search = Horde_Util::getPost('search');
-
- if (!empty($search) || $args['initial']) {
- $args += array(
- 'after' => intval(Horde_Util::getPost('after')),
- 'before' => intval(Horde_Util::getPost('before'))
- );
- }
-
- if (empty($search)) {
- list($slice_start, $slice_end) = explode(':', Horde_Util::getPost('slice'), 2);
- $args += array(
- 'slice_start' => intval($slice_start),
- 'slice_end' => intval($slice_end)
- );
- } else {
- $search = Horde_Serialize::unserialize($search, Horde_Serialize::JSON);
- $args += array(
- 'search_uid' => isset($search->imapuid) ? $search->imapuid : null,
- 'search_unseen' => isset($search->unseen) ? $search->unseen : null
- );
- }
-
- $list_msg = new IMP_Views_ListMessages();
- return $list_msg->listMessages($args);
-}
-
-function _getIdxString($indices)
-{
- $i = each($indices);
- return reset($i['value']) . IMP::IDX_SEP . $i['key'];
-}
-
-function _getPollInformation($mbox)
-{
- $imptree = IMP_Imap_Tree::singleton();
- $elt = $imptree->get($mbox);
- if ($imptree->isPolled($elt)) {
- $info = $imptree->getElementInfo($mbox);
- return array($mbox => isset($info['unseen']) ? intval($info['unseen']) : 0);
- }
- return array();
-}
-
-function _getQuota()
-{
- if (isset($_SESSION['imp']['quota']) &&
- is_array($_SESSION['imp']['quota'])) {
- $quotadata = IMP::quotaData(false);
- if (!empty($quotadata)) {
- return array('p' => round($quotadata['percent']), 'm' => $quotadata['message']);
- }
- }
-
- return null;
-}
-
-// Need to load Horde_Util:: to give us access to Horde_Util::getPathInfo().
-require_once dirname(__FILE__) . '/lib/Application.php';
-$action = basename(Horde_Util::getPathInfo());
-if (empty($action)) {
- // This is the only case where we really don't return anything, since
- // the frontend can be presumed not to make this request on purpose.
- // Other missing data cases we return a response of boolean false.
- exit;
-}
-
-// The following actions do not need write access to the session and
-// should be opened read-only for performance reasons.
-$session_control = null;
-if (in_array($action, array('chunkContent', 'Html2Text', 'Text2Html', 'GetReplyData'))) {
- $session_control = 'readonly';
-}
-
-try {
- Horde_Registry::appInit('imp', array('authentication' => 'throw', 'session_control' => $session_control));
-} catch (Horde_Exception $e) {
- /* Handle session timeouts when they come from an AJAX request. */
- if (($e->getCode() == Horde_Registry::AUTH_FAILURE) &&
- ($action != 'LogOut')) {
- $notification = Horde_Notification::singleton();
- $imp_notify = $notification->attach('status', array('viewmode' => 'dimp'), 'IMP_Notification_Listener_Status');
- $notification->push(str_replace('&', '&', Horde_Auth::getLogoutUrl(array('reason' => Horde_Auth::REASON_SESSION))), 'dimp.timeout', array('content.raw'));
- Horde::sendHTTPResponse(Horde::prepareResponse(null, $imp_notify), 'json');
- exit;
- }
-
- Horde_Auth::authenticateFailure('imp', $e);
-}
-
-// Process common request variables.
-$mbox = Horde_Util::getPost('view');
-$indices = $imp_imap->ob()->utils->fromSequenceString(Horde_Util::getPost('uid'));
-$cacheid = Horde_Util::getPost('cacheid');
-
-// Open an output buffer to ensure that we catch errors that might break JSON
-// encoding.
-ob_start();
-
-$notify = true;
-$check_uidvalidity = $result = false;
-
-switch ($action) {
-case 'LogOut':
- /* Handle logout requests. This needs to be done here, rather than on the
- * browser, because the logout tokens might otherwise expire. */
- Horde::redirect(str_replace('&', '&', Horde::getServiceLink('logout', 'imp')));
- exit;
-
-case 'CreateFolder':
- if (empty($mbox)) {
- break;
- }
-
- $imptree = IMP_Imap_Tree::singleton();
- $imptree->eltDiffStart();
-
- $imp_folder = IMP_Folder::singleton();
-
- $new = Horde_String::convertCharset($mbox, Horde_Nls::getCharset(), 'UTF7-IMAP');
- try {
- $new = $imptree->createMailboxName(Horde_Util::getPost('parent'), $new);
- $result = $imp_folder->create($new, $prefs->getValue('subscribe'));
- if ($result) {
- $result = IMP_Dimp::getFolderResponse($imptree);
- }
- } catch (Horde_Exception $e) {
- $notification->push($e, 'horde.error');
- $result = false;
- }
- break;
-
-case 'DeleteFolder':
- if (empty($mbox)) {
- break;
- }
-
- $imptree = IMP_Imap_Tree::singleton();
- $imptree->eltDiffStart();
-
- if ($imp_search->isEditableVFolder($mbox)) {
- $notification->push(sprintf(_("Deleted Virtual Folder \"%s\"."), $imp_search->getLabel($mbox)), 'horde.success');
- $imp_search->deleteSearchQuery($mbox);
- $result = true;
- } else {
- $imp_folder = IMP_Folder::singleton();
- $result = $imp_folder->delete(array($mbox));
- }
-
- if ($result) {
- $result = IMP_Dimp::getFolderResponse($imptree);
- }
- break;
-
-case 'RenameFolder':
- $old = Horde_Util::getPost('old_name');
- $new_parent = Horde_Util::getPost('new_parent');
- $new = Horde_Util::getPost('new_name');
- if (!$old || !$new) {
- break;
- }
-
- $imptree = IMP_Imap_Tree::singleton();
- $imptree->eltDiffStart();
-
- $imp_folder = IMP_Folder::singleton();
-
- try {
- $new = $imptree->createMailboxName($new_parent, $new);
-
- $new = Horde_String::convertCharset($new, Horde_Nls::getCharset(), 'UTF7-IMAP');
- if ($old != $new) {
- $result = $imp_folder->rename($old, $new);
- if ($result) {
- $result = IMP_Dimp::getFolderResponse($imptree);
- }
- }
- } catch (Horde_Exception $e) {
- $notification->push($e, 'horde.error');
- $result = false;
- }
- break;
-
-case 'EmptyFolder':
- if (empty($mbox)) {
- break;
- }
-
- $imp_message = IMP_Message::singleton();
- $imp_message->emptyMailbox(array($mbox));
- $result = new stdClass;
- $result->mbox = $mbox;
- break;
-
-case 'FlagAll':
- $flags = Horde_Serialize::unserialize(Horde_Util::getPost('flags'), Horde_Serialize::JSON);
- if (empty($mbox) || empty($flags)) {
- break;
- }
-
- $set = Horde_Util::getPost('set');
-
- $imp_message = IMP_Message::singleton();
- $result = $imp_message->flagAllInMailbox($flags, array($mbox), $set);
-
- if ($result) {
- $result = new stdClass;
- $result->flags = $flags;
- $result->mbox = $mbox;
- if ($set) {
- $result->set = 1;
- }
-
- $poll = _getPollInformation($mbox);
- if (!empty($poll)) {
- $result->poll = array($mbox => $poll[$mbox]);
- }
- }
- break;
-
-case 'ListFolders':
- $imptree = IMP_Imap_Tree::singleton();
- $mask = IMP_Imap_Tree::FLIST_CONTAINER | IMP_Imap_Tree::FLIST_VFOLDER | IMP_Imap_Tree::FLIST_ELT;
- if (Horde_Util::getPost('unsub')) {
- $mask |= IMP_Imap_Tree::FLIST_UNSUB;
- }
-
- if (!Horde_Util::getPost('all')) {
- $mask |= IMP_Imap_Tree::FLIST_NOCHILDREN;
- if (Horde_Util::getPost('initial') || Horde_Util::getPost('reload')) {
- $mask |= IMP_Imap_Tree::FLIST_ANCESTORS | IMP_Imap_Tree::FLIST_SAMELEVEL;
- }
- }
-
- $folder_list = array();
- foreach (Horde_Serialize::unserialize($mbox, Horde_Serialize::JSON) as $val) {
- $folder_list += $imptree->folderList($mask, $val);
- }
-
- /* Add special folders explicitly to the initial folder list, since they
- * are ALWAYS displayed and may appear outside of the folder slice
- * requested. */
- if (Horde_Util::getPost('initial')) {
- foreach ($imptree->getSpecialMailboxes() as $val) {
- if (!is_array($val)) {
- $val = array($val);
- }
-
- foreach ($val as $val2) {
- if (!isset($folder_list[$val2]) &&
- ($elt = $imptree->element($val2))) {
- $folder_list[$val2] = $elt;
- }
- }
- }
- }
-
- $result = IMP_Dimp::getFolderResponse($imptree, array('a' => array_values($folder_list), 'c' => array(), 'd' => array()));
-
- $quota = _getQuota();
- if (!is_null($quota)) {
- $result['quota'] = $quota;
- }
- break;
-
-case 'Poll':
- $result = new stdClass;
-
- $imptree = IMP_Imap_Tree::singleton();
-
- $result->poll = array();
- foreach ($imptree->getPollList() as $val) {
- if ($info = $imptree->getElementInfo($val)) {
- $result->poll[$val] = intval($info['unseen']);
- }
- }
-
- $changed = false;
- if (!empty($mbox)) {
- $changed =_changed($mbox, $cacheid, $action);
- if ($changed) {
- $result->ViewPort = _getListMessages($mbox, true);
- }
- }
-
- if (!is_null($changed)) {
- $quota = _getQuota();
- if (!is_null($quota)) {
- $result->quota = $quota;
- }
- }
- break;
-
-case 'Subscribe':
- if ($prefs->getValue('subscribe')) {
- $imp_folder = IMP_Folder::singleton();
- $result = Horde_Util::getPost('sub')
- ? $imp_folder->subscribe(array($mbox))
- : $imp_folder->unsubscribe(array($mbox));
- }
- break;
-
-case 'ViewPort':
- if (empty($mbox)) {
- break;
- }
-
- /* Change sort preferences if necessary. */
- $sortby = Horde_Util::getPost('sortby');
- $sortdir = Horde_Util::getPost('sortdir');
- if (!is_null($sortby) || !is_null($sortdir)) {
- IMP::setSort($sortby, $sortdir, $mbox);
- }
-
- $changed = _changed($mbox, $cacheid, $action, false);
-
- if (is_null($changed)) {
- $list_msg = new IMP_Views_ListMessages();
- $result = new stdClass;
- $result->ViewPort = $list_msg->getBaseOb($mbox);
-
- $req_id = Horde_Util::getPost('requestid');
- if (!is_null($req_id)) {
- $result->ViewPort->requestid = intval($req_id);
- }
- } elseif ($changed ||
- Horde_Util::getPost('rangeslice') ||
- !Horde_Util::getPost('checkcache')) {
- $result = new stdClass;
- $result->ViewPort = _getListMessages($mbox, $changed);
- }
- break;
-
-case 'MoveMessage':
-case 'CopyMessage':
- $to = Horde_Util::getPost('tofld');
- if (!$to || empty($indices)) {
- break;
- }
-
- $change = ($action == 'MoveMessage')
- ? _changed($mbox, $cacheid, $action, true)
- : false;
-
- if (!is_null($change)) {
- $imp_message = IMP_Message::singleton();
-
- $result = $imp_message->copy($to, ($action == 'MoveMessage') ? 'move' : 'copy', $indices);
-
- if ($result) {
- if ($action == 'MoveMessage') {
- $result = _generateDeleteResult($mbox, $indices, $change);
- // Need to manually set remove to true since we want to remove
- // message from the list no matter the current pref settings.
- $result->deleted->remove = 1;
- }
-
- // Update poll information for destination folder if necessary.
- // Poll information for current folder will be added by
- // _generateDeleteResult() call above.
- $poll = _getPollInformation($to);
- if (!empty($poll)) {
- if (!isset($result->poll)) {
- $result->poll = array();
- }
- $result->poll = array_merge($result->poll, $poll);
- }
- } else {
- $check_uidvalidity = true;
- }
- }
- break;
-
-case 'FlagMessage':
- $flags = Horde_Util::getPost('flags');
- if (!$flags || empty($indices)) {
- break;
- }
- $flags = Horde_Serialize::unserialize($flags, Horde_Serialize::JSON);
-
- $set = $notset = array();
- foreach ($flags as $val) {
- if ($val[0] == '-') {
- $notset[] = substr($val, 1);
- } else {
- $set[] = $val;
- }
- }
-
- $imp_message = IMP_Message::singleton();
- if (!empty($set)) {
- $result = $imp_message->flag($set, $indices, true);
- }
- if (!empty($notset)) {
- $result = $imp_message->flag($notset, $indices, false);
- }
-
- if ($result) {
- $result = new stdClass;
- } else {
- $check_uidvalidity = true;
- }
- break;
-
-case 'DeleteMessage':
- if (empty($indices)) {
- break;
- }
-
- $imp_message = IMP_Message::singleton();
- $change = _changed($mbox, $cacheid, $action, true);
-
- if ($imp_message->delete($indices)) {
- $result = _generateDeleteResult($mbox, $indices, $change, !$prefs->getValue('hide_deleted') && !$prefs->getValue('use_trash'));
- } elseif (!is_null($change)) {
- $check_uidvalidity = true;
- }
- break;
-
-case 'AddContact':
- $email = Horde_Util::getPost('email');
- $name = Horde_Util::getPost('name');
- // Allow $name to be empty.
- if (empty($email)) {
- break;
- }
-
- try {
- IMP::addAddress($email, $name);
- $result = true;
- $notification->push(sprintf(_("%s was successfully added to your address book."), $name ? $name : $email), 'horde.success');
- } catch (Horde_Exception $e) {
- $notification->push($e, 'horde.error');
- $result = false;
- }
- break;
-
-case 'ReportSpam':
- $change = _changed($mbox, $cacheid, $action, false);
-
- if (IMP_Spam::reportSpam($indices, Horde_Util::getPost('spam') ? 'spam' : 'notspam')) {
- $result = _generateDeleteResult($mbox, $indices, $change);
- // If result is non-zero, then we know the message has been removed
- // from the current mailbox.
- $result->deleted->remove = 1;
- } elseif (!is_null($change)) {
- $check_uidvalidity = true;
- }
- break;
-
-case 'Blacklist':
- if (empty($indices)) {
- break;
- }
-
- $imp_filter = new IMP_Filter();
- if (Horde_Util::getPost('blacklist')) {
- $change = _changed($mbox, $cacheid, $action, false);
- if (!is_null($change)) {
- try {
- if ($imp_filter->blacklistMessage($indices, false)) {
- $result = _generateDeleteResult($mbox, $indices, $change);
- }
- } catch (Horde_Exception $e) {
- $check_uidvalidity = true;
- }
- }
- } else {
- try {
- $imp_filter->whitelistMessage($indices, false);
- } catch (Horde_Exception $e) {
- $check_uidvalidity = true;
- }
- }
- break;
-
-case 'ShowPreview':
- if (count($indices) != 1) {
- break;
- }
-
- $ptr = each($indices);
- $args = array(
- 'mailbox' => $ptr['key'],
- 'preview' => true,
- 'uid' => intval(reset($ptr['value']))
- );
-
- /* 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. */
- try {
- $imp_imap->ob()->openMailbox($ptr['key'], Horde_Imap_Client::OPEN_READWRITE);
- $show_msg = new IMP_Views_ShowMessage();
- $result = (object)$show_msg->showMessage($args);
- if (isset($result->error)) {
- $check_uidvalidity = true;
- }
- } catch (Horde_Imap_Client_Exception $e) {
- $result = new stdClass;
- $result->error = $e->getMessage();
- $result->errortype = 'horde.error';
- $result->mailbox = $args['mailbox'];
- $result->uid = $args['uid'];
- }
-
- break;
-
-case 'Html2Text':
- $result = new stdClass;
- // Need to replace line endings or else IE won't display line endings
- // properly.
- $result->text = str_replace("\n", "\r\n", Horde_Text_Filter::filter(Horde_Util::getPost('text'), 'html2text', array('charset' => Horde_Nls::getCharset())));
- break;
-
-case 'Text2Html':
- $result = new stdClass;
- $result->text = Horde_Text_Filter::filter(Horde_Util::getPost('text'), 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO_LINKURL, 'class' => null, 'callback' => null));
- break;
-
-case 'GetForwardData':
- $header = array();
- $msg = $header = null;
- $idx_string = _getIdxString($indices);
-
- try {
- $imp_contents = IMP_Contents::singleton($idx_string);
- $imp_compose = IMP_Compose::singleton(Horde_Util::getPost('imp_compose'));
- $imp_ui = new IMP_Ui_Compose();
- $fwd_msg = $imp_ui->getForwardData($imp_compose, $imp_contents, $idx_string);
- $header = $fwd_msg['headers'];
- $header['replytype'] = 'forward';
-
- $result = new stdClass;
- // Can't open read-only since we need to store the message cache id.
- $result->imp_compose = $imp_compose->getCacheId();
- $result->fwd_list = IMP_Dimp::getAttachmentInfo($imp_compose);
- $result->body = $fwd_msg['body'];
- $result->header = $header;
- $result->format = $fwd_msg['format'];
- $result->identity = $fwd_msg['identity'];
- } catch (Horde_Exception $e) {
- $notification->push($e, 'horde.error');
- $check_uidvalidity = true;
- }
- break;
-
-case 'GetReplyData':
- try {
- $imp_contents = IMP_Contents::singleton(_getIdxString($indices));
- $imp_compose = IMP_Compose::singleton(Horde_Util::getPost('imp_compose'));
- $reply_msg = $imp_compose->replyMessage(Horde_Util::getPost('type'), $imp_contents);
- $header = $reply_msg['headers'];
- $header['replytype'] = 'reply';
-
- $result = new stdClass;
- $result->format = $reply_msg['format'];
- $result->body = $reply_msg['body'];
- $result->header = $header;
- $result->identity = $reply_msg['identity'];
- } catch (Horde_Exception $e) {
- $notification->push($e, 'horde.error');
- $check_uidvalidity = true;
- }
- break;
-
-case 'CancelCompose':
-case 'DeleteDraft':
- $imp_compose = IMP_Compose::singleton(Horde_Util::getPost('imp_compose'));
- $imp_compose->destroy(false);
- $draft_uid = $imp_compose->getMetadata('draft_uid');
- if ($draft_uid && ($action == 'DeleteDraft')) {
- $imp_message = IMP_Message::singleton();
- $idx_array = array($draft_uid . IMP::IDX_SEP . IMP::folderPref($prefs->getValue('drafts_folder'), true));
- $imp_message->delete($idx_array, array('nuke' => true));
- }
- $result = true;
- break;
-
-case 'DeleteAttach':
- $atc = Horde_Util::getPost('atc_indices');
- if (!is_null($atc)) {
- $imp_compose = IMP_Compose::singleton(Horde_Util::getPost('imp_compose'));
- foreach ($imp_compose->deleteAttachment($atc) as $val) {
- $notification->push(sprintf(_("Deleted the attachment \"%s\"."), Horde_Mime::decode($val)), 'horde.success');
- }
- }
- break;
-
-case 'ShowPortal':
- // Load the block list. Blocks are located in $dimp_block_list.
- // KEY: Block label; VALUE: Horde_Block object
- require IMP_BASE . '/config/portal.php';
-
- $blocks = $linkTags = array();
- $css_load = array('imp' => true);
- foreach ($dimp_block_list as $title => $block) {
- if ($block['ob'] instanceof Horde_Block) {
- $app = $block['ob']->getApp();
- // TODO: Fix CSS.
- $content = $block['ob']->getContent();
- $css_load[$app] = true;
- // Don't do substitutions on our own blocks.
- if ($app != 'imp') {
- $content = preg_replace('/<a href="([^"]+)"/',
- '<a onclick="DimpBase.go(\'app:' . $app . '\', \'$1\');return false"',
- $content);
- if (preg_match_all('/<link .*?rel="stylesheet".*?\/>/',
- $content, $links)) {
- $content = str_replace($links[0], '', $content);
- foreach ($links[0] as $link) {
- if (preg_match('/href="(.*?)"/', $link, $href)) {
- $linkOb = new stdClass;
- $linkOb->href = $href[1];
- if (preg_match('/media="(.*?)"/', $link, $media)) {
- $linkOb->media = $media[1];
- }
- $linkTags[] = $linkOb;
- }
- }
- }
- }
- if (!empty($content)) {
- $entry = array(
- 'app' => $app,
- 'content' => $content,
- 'title' => $title,
- 'class' => empty($block['class']) ? 'headerbox' : $block['class'],
- );
- if (!empty($block['domid'])) {
- $entry['domid'] = $block['domid'];
- }
- if (!empty($block['tag'])) {
- $entry[$block['tag']] = true;
- }
- $blocks[] = $entry;
- }
- }
- }
-
- $result = new stdClass;
- $result->portal = '';
- if (!empty($blocks)) {
- $t = new Horde_Template(IMP_TEMPLATES . '/imp/');
- $t->set('block', $blocks);
- $result->portal = $t->fetch('portal.html');
- }
- $result->linkTags = $linkTags;
- break;
-
-case 'chunkContent':
- $chunk = basename(Horde_Util::getPost('chunk'));
- if (!empty($chunk)) {
- $result = new stdClass;
- $result->chunk = Horde_Util::bufferOutput('include', IMP_TEMPLATES . '/chunks/' . $chunk . '.php');
- }
- break;
-
-case 'PurgeDeleted':
- $change = _changed($mbox, $cacheid, $action, $indices);
- if (!is_null($change)) {
- if (!$change) {
- $sort = IMP::getSort($mbox);
- $change = ($sort['by'] == Horde_Imap_Client::SORT_THREAD);
- }
- $imp_message = IMP_Message::singleton();
- $expunged = $imp_message->expungeMailbox(array($mbox => 1), array('list' => true));
- if (!empty($expunged[$mbox])) {
- $expunge_count = count($expunged[$mbox]);
- $display_folder = IMP::displayFolder($mbox);
- if ($expunge_count == 1) {
- $notification->push(sprintf(_("1 message was purged from \"%s\"."), $display_folder), 'horde.success');
- } else {
- $notification->push(sprintf(_("%s messages were purged from \"%s\"."), $expunge_count, $display_folder), 'horde.success');
- }
- $result = _generateDeleteResult($mbox, $expunged, $change);
- // Need to manually set remove to true since we want to remove
- // message from the list no matter the current pref settings.
- $result->deleted->remove = 1;
- }
- }
- break;
-
-case 'ModifyPoll':
- if (empty($mbox)) {
- break;
- }
-
- $add = Horde_Util::getPost('add');
- $display_folder = IMP::displayFolder($mbox);
-
- $imptree = IMP_Imap_Tree::singleton();
-
- $result = new stdClass;
- $result->add = intval($add);
- $result->folder = $mbox;
-
- if ($add) {
- $imptree->addPollList($mbox);
- if ($info = $imptree->getElementInfo($mbox)) {
- $result->poll = array($mbox => intval($info['unseen']));
- }
- $notification->push(sprintf(_("\"%s\" mailbox now polled for new mail."), $display_folder), 'horde.success');
- } else {
- $imptree->removePollList($mbox);
- $notification->push(sprintf(_("\"%s\" mailbox no longer polled for new mail."), $display_folder), 'horde.success');
- }
- break;
-
-case 'SendMDN':
- $uid = Horde_Util::getPost('uid');
- if (empty($mbox) || empty($uid)) {
- break;
- }
-
- /* Get the IMP_Headers:: object. */
- try {
- $fetch_ret = $imp_imap->ob()->fetch($mbox, array(
- Horde_Imap_Client::FETCH_HEADERTEXT => array(array('parse' => true, 'peek' => false))
- ), array('ids' => array($uid)));
- } catch (Horde_Imap_Client_Exception $e) {
- break;
- }
-
- $imp_ui = new IMP_Ui_Message();
- $imp_ui->MDNCheck($mbox, $uid, $reset($fetch_ret[$uid]['headertext']), true);
- break;
-
-case 'PGPSymmetric':
-case 'PGPPersonal':
-case 'SMIMEPersonal':
- $result = new stdClass;
- $result->success = false;
-
- $passphrase = Horde_Util::getFormData('dialog_input');
-
- if ($action == 'SMIMEPersonal') {
- $imp_smime = Horde_Crypt::singleton(array('IMP', 'Smime'));
- try {
- Horde::requireSecureConnection();
- if ($passphrase) {
- if ($imp_smime->storePassphrase($passphrase)) {
- $result->success = 1;
- } else {
- $result->error = _("Invalid passphrase entered.");
- }
- } else {
- $result->error = _("No passphrase entered.");
- }
- } catch (Horde_Exception $e) {
- $result->error = $e->getMessage();
- }
- } else {
- $imp_pgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
- try {
- Horde::requireSecureConnection();
- if ($passphrase) {
- if ($imp_pgp->storePassphrase(($action == 'PGPSymmetric') ? 'symmetric' : 'personal', $passphrase, Horde_Util::getFormData('symmetricid'))) {
- $result->success = 1;
- } else {
- $result->error = _("Invalid passphrase entered.");
- }
- } else {
- $result->error = _("No passphrase entered.");
- }
- } catch (Horde_Exception $e) {
- $result->error = $e->getMessage();
- }
- }
-
- if ($_SESSION['imp']['view'] != 'dimp') {
- $notify = false;
- }
-
- break;
-}
-
-if ($check_uidvalidity) {
- try {
- $imp_imap->checkUidvalidity($mbox);
- } catch (Horde_Exception $e) {
- if (!is_object($result)) {
- $result = new stdClass;
- }
- $result->ViewPort = _getListMessages($mbox, true);
- }
-}
-
-// Clear the output buffer that we started above, and log any unexpected
-// output at a DEBUG level.
-if (ob_get_length()) {
- Horde::logMessage('DIMP: unexpected output: ' . ob_get_clean(), __FILE__, __LINE__, PEAR_LOG_DEBUG);
-}
-
-// Send the final result.
-Horde::sendHTTPResponse(Horde::prepareResponse($result, $notify ? $GLOBALS['imp_notify'] : null), 'json');
v5.0-git
--------
+[mms] Move AJAX processing framework to Horde (Request #4561).
[mms] If selected message(s) disappear from mailbox, gracefully handle in the
user interface (DIMP).
[mms] Only update search mailbox on explicit user action (Request #7297)
this.viewport = new ViewPort({
// Mandatory config
- ajax_url: DIMP.conf.URI_AJAX + '/ViewPort',
+ ajax_url: DIMP.conf.URI_AJAX + 'ViewPort',
container: container,
onContent: function(r, mode) {
var bg, re, u,
case 'ctx_folder_empty':
tmp = baseelt.up('LI');
if (window.confirm(DIMP.text.empty_folder.replace(/%s/, tmp.readAttribute('title')))) {
- DimpCore.doAction('EmptyFolder', { view: tmp.retrieve('mbox') }, { callback: this._emptyFolderCallback.bind(this) });
+ DimpCore.doAction('EmptyFolder', { mbox: tmp.retrieve('mbox') }, { callback: this._emptyFolderCallback.bind(this) });
}
break;
case 'ctx_vfolder_delete':
tmp = baseelt.up('LI');
if (window.confirm(DIMP.text.delete_folder.replace(/%s/, tmp.readAttribute('title')))) {
- DimpCore.doAction('DeleteFolder', { view: tmp.retrieve('mbox') }, { callback: this._folderCallback.bind(this) });
+ DimpCore.doAction('DeleteMailbox', { mbox: tmp.retrieve('mbox') }, { callback: this._folderCallback.bind(this) });
}
break;
dropbase = (drop == $('dropbase'));
if (dropbase ||
(ftype != 'special' && !this.isSubfolder(drag, drop))) {
- DimpCore.doAction('RenameFolder', { old_name: drag.retrieve('mbox'), new_parent: dropbase ? '' : foldername, new_name: drag.retrieve('l') }, { callback: this._folderCallback.bind(this) });
+ DimpCore.doAction('RenameMailbox', { old_name: drag.retrieve('mbox'), new_parent: dropbase ? '' : foldername, new_name: drag.retrieve('l') }, { callback: this._folderCallback.bind(this) });
}
} else if (ftype != 'container') {
sel = this.viewport.getSelected();
if (uids.size()) {
if (e.memo.dragevent.ctrlKey) {
- DimpCore.doAction('CopyMessage', this.viewport.addRequestParams({ tofld: foldername }), { uids: uids });
+ DimpCore.doAction('CopyMessages', this.viewport.addRequestParams({ mboxto: foldername }), { uids: uids });
} else if (this.folder != foldername) {
// Don't allow drag/drop to the current folder.
this.updateFlag(uids, '\\deleted', true);
- DimpCore.doAction('MoveMessage', this.viewport.addRequestParams({ tofld: foldername }), { uids: uids });
+ DimpCore.doAction('MoveMessages', this.viewport.addRequestParams({ mboxto: foldername }), { uids: uids });
}
}
}
case 'rename':
folder = folder.up('LI');
if (folder.retrieve('l') != val) {
- action = 'RenameFolder';
- params = { old_name: folder.retrieve('mbox'),
- new_parent: folder.up().hasClassName('folderlist') ? '' : folder.up(1).previous().retrieve('mbox'),
- new_name: val };
+ action = 'RenameMailbox';
+ params = {
+ old_name: folder.retrieve('mbox'),
+ new_parent: folder.up().hasClassName('folderlist') ? '' : folder.up(1).previous().retrieve('mbox'),
+ new_name: val
+ };
}
break;
case 'create':
case 'createsub':
- action = 'CreateFolder';
- params = { view: val };
+ action = 'CreateMailbox';
+ params = { mbox: val };
if (mode == 'createsub') {
params.parent = folder.up('LI').retrieve('mbox');
}
_flagAllCallback: function(r)
{
- if (r.response) {
- if (r.response.mbox == this.folder) {
- r.response.flags.each(function(f) {
- this.updateFlag(this.viewport.createSelection('rownum', $A($R(1, this.viewport.getMetaData('total_rows')))), f, r.response.set);
- }, this);
- }
+ if (r.response &&
+ r.response.mbox == this.folder) {
+ r.response.flags.each(function(f) {
+ this.updateFlag(this.viewport.createSelection('rownum', $A($R(1, this.viewport.getMetaData('total_rows')))), f, r.response.set);
+ }, this);
}
},
this._listFolders({
all: Number(mode == 'expall'),
callback: this._toggleSubFolder.bind(this, base, mode, noeffect),
- view: need
+ mboxes: need
});
return;
} else if (mode == 'tog') {
params = params || {};
params.unsub = Number(this.showunsub);
- if (!Object.isArray(params.view)) {
- params.view = [ params.view ];
+ if (!Object.isArray(params.mboxes)) {
+ params.mboxes = [ params.mboxes ];
}
- params.view = params.view.toJSON();
+ params.mboxes = params.mboxes.toJSON();
if (params.callback) {
cback = function(func, r) { this._folderLoadCallback(r, func); }.bind(this, params.callback);
cback = this._folderLoadCallback.bind(this);
}
- DimpCore.doAction('ListFolders', params, { callback: cback });
+ DimpCore.doAction('ListMailboxes', params, { callback: cback });
},
// Folder actions.
this.deleteFolderElt(elt.readAttribute('id'), true);
}, this);
- this._listFolders({ reload: 1, view: this.folder });
+ this._listFolders({ reload: 1, mboxes: this.folder });
},
subscribeFolder: function(f, sub)
{
var fid = this.getFolderId(f);
- DimpCore.doAction('Subscribe', { view: f, sub: Number(sub) });
+ DimpCore.doAction('Subscribe', { mbox: f, sub: Number(sub) });
if (this.showunsub) {
[ $(fid) ].invoke(sub ? 'removeClassName' : 'addClassName', 'unsubFolder');
opts.vs = vs;
- this._doMsgAction('DeleteMessage', opts, {});
+ this._doMsgAction('DeleteMessages', opts, {});
this.updateFlag(vs, '\\deleted', true);
},
this.updateFlag(vs, flag, set);
if (!opts.noserver) {
- DimpCore.doAction('FlagMessage', { flags: flags.toJSON(), view: this.folder }, { uids: vs });
+ DimpCore.doAction('FlagMessages', { flags: flags.toJSON(), view: this.folder }, { uids: vs });
}
},
// mbox = (string) The mailbox to flag
flagAll: function(type, set, mbox)
{
- DimpCore.doAction('FlagAll', { flags: [ type ].toJSON(), set: Number(set), view: mbox }, { callback: this._flagAllCallback.bind(this) });
+ DimpCore.doAction('FlagAll', { flags: [ type ].toJSON(), set: Number(set), mbox: mbox }, { callback: this._flagAllCallback.bind(this) });
},
hasFlag: function(f, r)
modifyPoll: function(folder, add)
{
- DimpCore.doAction('ModifyPoll', { view: folder, add: Number(add) }, { callback: this._modifyPollCallback.bind(this) });
+ DimpCore.doAction('ModifyPoll', { add: Number(add), mbox: folder }, { callback: this._modifyPollCallback.bind(this) });
},
_modifyPollCallback: function(r)
{
r = r.response;
- var f = r.folder, fid, p = { response: { poll: {} } };
+ var f = r.mbox, fid, p = { response: { poll: {} } };
fid = $(this.getFolderId(f));
if (r.add) {
if (!r.add) {
fid.store('u', null);
- this.updateUnseenStatus(r.folder, 0);
+ this.updateUnseenStatus(f, 0);
}
},
/* Create the folder list. Any pending notifications will be caught
* via the return from this call. */
- this._listFolders({ initial: 1, view: this.folder} );
+ this._listFolders({ initial: 1, mboxes: this.folder} );
this._setQsearchText(true);
{
action = action.startsWith('*')
? action.substring(1)
- : DIMP.conf.URI_AJAX + '/' + action;
+ : DIMP.conf.URI_AJAX + action;
params = $H(params);
opts = opts || {};
var log = 0;
switch (m.type) {
- case 'dimp.timeout':
+ case 'horde.ajaxtimeout':
this.logout(m.message);
return true;
logout: function(url)
{
this.is_logout = true;
- this.redirect(url || (DIMP.conf.URI_AJAX + '/LogOut'));
+ this.redirect(url || (DIMP.conf.URI_AJAX + 'LogOut'));
},
redirect: function(url, force)
--- /dev/null
+<?php
+/**
+ * Defines the AJAX interface for IMP.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @package IMP
+ */
+class IMP_Ajax_Application extends Horde_Ajax_Application_Base
+{
+ /**
+ * The list of actions that require readonly access to the session.
+ *
+ * @var array
+ */
+ protected $_readOnly = array(
+ 'GetReplyData', 'Html2Text', 'Text2Html'
+ );
+
+ /**
+ * Returns a notification handler object to use to output any
+ * notification messages triggered by the AJAX action.
+ *
+ * @return Horde_Notification_Handler_Base The notification handler.
+ */
+ public function notificationHandler()
+ {
+ return $GLOBALS['imp_notify'];
+ }
+
+ /**
+ * AJAX action: Create a mailbox.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'mbox' - (string) The name of the new mailbox.
+ * 'parent' - (string) The parent mailbox.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'a' - (array) Mailboxes that were added.
+ * 'c' - (array) Mailboxes that were changed.
+ * 'd' - (array) Mailboxes that were deleted.
+ * </pre>
+ */
+ public function CreateMailbox($vars)
+ {
+ if (!$vars->mbox) {
+ return false;
+ }
+
+ $imptree = IMP_Imap_Tree::singleton();
+ $imptree->eltDiffStart();
+
+ $imp_folder = IMP_Folder::singleton();
+
+ $new = Horde_String::convertCharset($vars->mbox, Horde_Nls::getCharset(), 'UTF7-IMAP');
+ try {
+ $new = $imptree->createMailboxName($vars->parent, $new);
+ $result = $imp_folder->create($new, $GLOBALS['prefs']->getValue('subscribe'));
+ if ($result) {
+ $result = IMP_Dimp::getFolderResponse($imptree);
+ }
+ } catch (Horde_Exception $e) {
+ $GLOBALS['notification']->push($e, 'horde.error');
+ $result = false;
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Delete a mailbox.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'mbox' - (string) The full mailbox name to delete.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'a' - (array) Mailboxes that were added.
+ * 'c' - (array) Mailboxes that were changed.
+ * 'd' - (array) Mailboxes that were deleted.
+ * </pre>
+ */
+ public function DeleteMailbox($vars)
+ {
+ if (!$vars->mbox) {
+ return false;
+ }
+
+ $imptree = IMP_Imap_Tree::singleton();
+ $imptree->eltDiffStart();
+
+ if ($imp_search->isEditableVFolder($vars->mbox)) {
+ $GLOBALS['notification']->push(sprintf(_("Deleted Virtual Folder \"%s\"."), $imp_search->getLabel($vars->mbox)), 'horde.success');
+ $imp_search->deleteSearchQuery($vars->mbox);
+ $result = true;
+ } else {
+ $imp_folder = IMP_Folder::singleton();
+ $result = $imp_folder->delete(array($vars->mbox));
+ }
+
+ return $result
+ ? IMP_Dimp::getFolderResponse($imptree)
+ : $result;
+ }
+
+ /**
+ * AJAX action: Rename a mailbox.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'new_name' - (string) New mailbox name (child node).
+ * 'new_parent' - (string) New parent name.
+ * 'old_name' - (string) Full name of old mailbox.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'a' - (array) Mailboxes that were added.
+ * 'c' - (array) Mailboxes that were changed.
+ * 'd' - (array) Mailboxes that were deleted.
+ * </pre>
+ */
+ public function RenameMailbox($vars)
+ {
+ if (!$vars->old_name || !$vars->new_name) {
+ return false;
+ }
+
+ $imptree = IMP_Imap_Tree::singleton();
+ $imptree->eltDiffStart();
+
+ $imp_folder = IMP_Folder::singleton();
+ $result = false;
+
+ try {
+ $new = Horde_String::convertCharset($imptree->createMailboxName($vars->new_parent, $vars->new_name), Horde_Nls::getCharset(), 'UTF7-IMAP');
+
+ if (($vars->old_name != $new) &&
+ $imp_folder->rename($vars->old_name, $new)) {
+ $result = IMP_Dimp::getFolderResponse($imptree);
+ }
+ } catch (Horde_Exception $e) {
+ $GLOBALS['notification']->push($e, 'horde.error');
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Empty a mailbox.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'mbox' - (string) The full mailbox name to empty.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'mbox' - (string) The mailbox that was emptied.
+ * </pre>
+ */
+ public function EmptyMailbox($vars)
+ {
+ if (!$vars->mbox) {
+ return false;
+ }
+
+ $imp_message = IMP_Message::singleton();
+ $imp_message->emptyMailbox(array($vars->mbox));
+
+ $result = new stdClass;
+ $result->mbox = $vars->mbox;
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Flag all messages in a mailbox.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'flags' - (string) The flags to set (JSON serialized array).
+ * 'mbox' - (string) The full malbox name.
+ * 'set' - (integer) Set the flags?
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'flags' - (array) The list of flags that were set.
+ * 'mbox' - (string) The full mailbox name.
+ * 'poll' - (array) Mailbox names as the keys, number of unseen messages
+ * as the values.
+ * 'set' - (integer) 1 if the flag was set. Unset otherwise.
+ * </pre>
+ */
+ public function FlagAll($vars)
+ {
+ $flags = Horde_Serialize::unserialize($vars->flags, Horde_Serialize::JSON);
+ if (!$vars->mbox || empty($flags)) {
+ return false;
+ }
+
+ $imp_message = IMP_Message::singleton();
+ $result = $imp_message->flagAllInMailbox($flags, array($vars->mbox), $vars->set);
+
+ if ($result) {
+ $result = new stdClass;
+ $result->flags = $flags;
+ $result->mbox = $vars->mbox;
+ if ($vars->set) {
+ $result->set = 1;
+ }
+
+ $poll = $this->_getPollInformation($vars->mbox);
+ if (!empty($poll)) {
+ $result->poll = array($vars->mbox => $poll[$vars->mbox]);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: List mailboxes.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'all' - (integer) 1 to show all mailboxes.
+ * 'initial' - (string) 1 to indicate the initial request for mailbox
+ * list.
+ * 'mboxes' - (string) The list of mailboxes to process (JSON encoded
+ * array).
+ * 'reload' - (integer) 1 to force reload of mailboxes.
+ * 'unsub' - (integer) 1 to show unsubscribed mailboxes.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'a' - (array) Mailboxes that were added.
+ * 'c' - (array) Mailboxes that were changed.
+ * 'd' - (array) Mailboxes that were deleted.
+ * 'quota' - (array) See _getQuota().
+ * </pre>
+ */
+ public function ListMailboxes($vars)
+ {
+ $imptree = IMP_Imap_Tree::singleton();
+ $mask = IMP_Imap_Tree::FLIST_CONTAINER | IMP_Imap_Tree::FLIST_VFOLDER | IMP_Imap_Tree::FLIST_ELT;
+ if ($vars->unsub) {
+ $mask |= IMP_Imap_Tree::FLIST_UNSUB;
+ }
+
+ if (!$vars->all) {
+ $mask |= IMP_Imap_Tree::FLIST_NOCHILDREN;
+ if ($vars->initial || $vars->reload) {
+ $mask |= IMP_Imap_Tree::FLIST_ANCESTORS | IMP_Imap_Tree::FLIST_SAMELEVEL;
+ }
+ }
+
+ $folder_list = array();
+ foreach (Horde_Serialize::unserialize($vars->mboxes, Horde_Serialize::JSON) as $val) {
+ $folder_list += $imptree->folderList($mask, $val);
+ }
+
+ /* Add special folders explicitly to the initial folder list, since
+ * they are ALWAYS displayed and may appear outside of the folder
+ * slice requested. */
+ if ($vars->initial) {
+ foreach ($imptree->getSpecialMailboxes() as $val) {
+ if (!is_array($val)) {
+ $val = array($val);
+ }
+
+ foreach ($val as $val2) {
+ if (!isset($folder_list[$val2]) &&
+ ($elt = $imptree->element($val2))) {
+ $folder_list[$val2] = $elt;
+ }
+ }
+ }
+ }
+
+ $result = IMP_Dimp::getFolderResponse($imptree, array(
+ 'a' => array_values($folder_list),
+ 'c' => array(),
+ 'd' => array()
+ ));
+
+ $quota = $this->_getQuota();
+ if (!is_null($quota)) {
+ $result['quota'] = $quota;
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Poll mailboxes.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _changed() and _viewPortData().
+ * Additional variables used:
+ * <pre>
+ * 'view' - (string) The current view (mailbox).
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'poll' - (array) Mailbox names as the keys, number of unseen messages
+ * as the values.
+ * 'quota' - (array) See _getQuota().
+ * 'ViewPort' - (object) See _viewPortData().
+ * </pre>
+ */
+ public function Poll($vars)
+ {
+ $changed = false;
+ $imptree = IMP_Imap_Tree::singleton();
+
+ $result = new stdClass;
+ $result->poll = array();
+
+ foreach ($imptree->getPollList() as $val) {
+ if ($info = $imptree->getElementInfo($val)) {
+ $result->poll[$val] = intval($info['unseen']);
+ }
+ }
+
+ if ($vars->view &&
+ ($changed = $this->_changed($vars))) {
+ $result->ViewPort = $this->_viewPortData($vars, true);
+ }
+
+ if (!is_null($changed)) {
+ $quota = $this->_getQuota();
+ if (!is_null($quota)) {
+ $result->quota = $quota;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Modify list of polled mailboxes.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'add' - (integer) 1 to add to the poll list, 0 to remove.
+ * 'mbox' - (string) The full mailbox name to modify.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'add' - (integer) 1 if added to the poll list, 0 if removed.
+ * 'mbox' - (string) The full mailbox name modified.
+ * 'poll' - (array) Mailbox names as the keys, number of unseen messages
+ * as the values.
+ * </pre>
+ */
+ public function ModifyPoll($vars)
+ {
+ if (!$vars->mbox) {
+ return false;
+ }
+
+ $display_folder = IMP::displayFolder($vars->mbox);
+
+ $imptree = IMP_Imap_Tree::singleton();
+
+ $result = new stdClass;
+ $result->add = intval($vars->add);
+ $result->mbox = $vars->mbox;
+
+ if ($vars->add) {
+ $imptree->addPollList($vars->view);
+ if ($info = $imptree->getElementInfo($vars->view)) {
+ $result->poll = array($vars->view => intval($info['unseen']));
+ }
+ $GLOBALS['notification']->push(sprintf(_("\"%s\" mailbox now polled for new mail."), $display_folder), 'horde.success');
+ } else {
+ $imptree->removePollList($vars->view);
+ $GLOBALS['notification']->push(sprintf(_("\"%s\" mailbox no longer polled for new mail."), $display_folder), 'horde.success');
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: [un]Subscribe to a mailbox.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'mbox' - (string) The full mailbox name to [un]subscribe to.
+ * 'sub' - (integer) 1 to subscribe, empty to unsubscribe.
+ * </pre>
+ *
+ * @return boolean True on success, false on failure.
+ */
+ public function Subscribe($vars)
+ {
+ if (!$GLOBALS['prefs']->getValue('subscribe')) {
+ return false;
+ }
+
+ $imp_folder = IMP_Folder::singleton();
+ return $vars->sub
+ ? $imp_folder->subscribe(array($vars->mbox))
+ : $imp_folder->unsubscribe(array($vars->mbox));
+ }
+
+ /**
+ * AJAX action: Output ViewPort data.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _changed() and _viewPortData().
+ * Additional variables used:
+ * <pre>
+ * 'checkcache' - (integer) If 1, only send data if cache has been
+ * invalidated.
+ * 'rangeslice' - (string) Range slice. See js/ViewPort.js.
+ * 'requestid' - (string) Request ID. See js/ViewPort.js.
+ * 'sortby' - (integer) The Horde_Imap_Client sort constant.
+ * 'sortdir' - (integer) 0 for ascending, 1 for descending.
+ * 'view' - (string) The current full mailbox name.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'ViewPort' - (object) See _viewPortData().
+ * </pre>
+ */
+ public function ViewPort($vars)
+ {
+ if (!$vars->view) {
+ return false;
+ }
+
+ /* Change sort preferences if necessary. */
+ if (isset($vars->sortby) || isset($vars->sortdir)) {
+ IMP::setSort($vars->sortby, $vars->sortdir, $vars->view);
+ }
+
+ $changed = $this->_changed($vars, false);
+
+ if (is_null($changed)) {
+ $list_msg = new IMP_Views_ListMessages();
+ $result = new stdClass;
+ $result->ViewPort = $list_msg->getBaseOb($vars->view);
+
+ $req_id = $vars->requestid;
+ if (!is_null($req_id)) {
+ $result->ViewPort->requestid = intval($req_id);
+ }
+ } elseif ($changed || $vars->rangeslice || !$vars->checkcache) {
+ $result = new stdClass;
+ $result->ViewPort = $this->_viewPortData($vars, $changed);
+ } else {
+ $result = false;
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Move messages.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _changed(), _generateDeleteResult(), and
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'mboxto' - (string) Mailbox to move the message to.
+ * 'uid' - (string) Indices of the messages to move (IMAP sequence
+ * string).
+ * </pre>
+ *
+ * @return mixed False on failure, or an object (see
+ * _generateDeleteResult() for format).
+ */
+ public function MoveMessages($vars)
+ {
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ if (!$vars->tofld || empty($indices)) {
+ return false;
+ }
+
+ $change = $this->_changed($vars, true);
+
+ if (is_null($change)) {
+ return false;
+ }
+
+ $imp_message = IMP_Message::singleton();
+ $result = $imp_message->copy($vars->tofld, 'move', $indices);
+
+ if ($result) {
+ $result = $this->_generateDeleteResult($vars, $indices, $change);
+ /* Need to manually set remove to true since we want to remove
+ * message from the list no matter the current pref
+ * settings. */
+ $result->deleted->remove = 1;
+
+ /* Update poll information for destination folder if necessary.
+ * Poll information for current folder will be added by
+ * _generateDeleteResult() call above. */
+ if ($poll = $this->_getPollInformation($vars->tofld)) {
+ $result->poll = array_merge(isset($result->poll) ? $result->poll : array(), $poll);
+ }
+ } else {
+ $result = $this->_checkUidvalidity($vars);
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Copy messages.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'mboxto' - (string) Mailbox to move the message to.
+ * 'uid' - (string) Indices of the messages to copy (IMAP sequence
+ * string).
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'ViewPort' - (object) See _viewPortData().
+ * 'poll' - (array) Mailbox names as the keys, number of unseen messages
+ * as the values.
+ * </pre>
+ */
+ public function CopyMessages($vars)
+ {
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ if (!$vars->mboxto || empty($indices)) {
+ return false;
+ }
+
+ $imp_message = IMP_Message::singleton();
+
+ if ($result = $imp_message->copy($vars->mboxto, 'copy', $indices)) {
+ if ($poll = _getPollInformation($vars->mboxto)) {
+ $result->poll = array_merge(isset($result->poll) ? $result->poll : array(), $poll);
+ }
+ } else {
+ $result = $this->_checkUidvalidity($vars);
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Flag messages.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'flags' - (string) The flags to set (JSON serialized array).
+ * 'uid' - (string) Indices of the messages to flag (IMAP sequence
+ * string).
+ * </pre>
+ *
+ * @return mixed True on success, on failure an object with these
+ * entries:
+ * <pre>
+ * 'ViewPort' - (object) See _viewPortData().
+ * </pre>
+ */
+ public function FlagMessages($vars)
+ {
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ if (!$vars->flags || empty($indices)) {
+ return false;
+ }
+
+ $flags = Horde_Serialize::unserialize($vars->flags, Horde_Serialize::JSON);
+ $imp_message = IMP_Message::singleton();
+ $result = false;
+ $set = $notset = array();
+
+ foreach ($flags as $val) {
+ if ($val[0] == '-') {
+ $notset[] = substr($val, 1);
+ } else {
+ $set[] = $val;
+ }
+ }
+
+ if (!empty($set)) {
+ $result = $imp_message->flag($set, $indices, true);
+ }
+
+ if (!empty($notset)) {
+ $result = $imp_message->flag($notset, $indices, false);
+ }
+
+ return $result
+ ? true
+ : $this->_checkUidvalidity($vars);
+ }
+
+ /**
+ * AJAX action: Delete messages.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _changed(), _generateDeleteResult(), and
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'uid' - (string) Indices of the messages to delete (IMAP sequence
+ * string).
+ * </pre>
+ *
+ * @return mixed False on failure, or an object (see
+ * _generateDeleteResult() for format).
+ */
+ public function DeleteMessages($vars)
+ {
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ if (empty($indices)) {
+ return false;
+ }
+
+ $imp_message = IMP_Message::singleton();
+ $change = $this->_changed($vars, true);
+
+ if ($imp_message->delete($indices)) {
+ return $this->_generateDeleteResult($vars, $indices, $change, !$GLOBALS['prefs']->getValue('hide_deleted') && !$GLOBALS['prefs']->getValue('use_trash'));
+ }
+
+ return is_null($change)
+ ? false
+ : $this->_checkUidvalidity($vars);
+ }
+
+ /**
+ * AJAX action: Add contact.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'email' - (string) The email address to name.
+ * 'name' - (string) The name associated with the email address.
+ * </pre>
+ *
+ * @return boolean True on success, false on failure.
+ */
+ public function AddContact($vars)
+ {
+ // Allow name to be empty.
+ if (!$vars->email) {
+ return false;
+ }
+
+ try {
+ IMP::addAddress($vars->email, $vars->name);
+ $GLOBALS['notification']->push(sprintf(_("%s was successfully added to your address book."), $vars->name ? $vars->name : $vars->email), 'horde.success');
+ return true;
+ } catch (Horde_Exception $e) {
+ $GLOBALS['notification']->push($e, 'horde.error');
+ return false;
+ }
+ }
+
+ /**
+ * AJAX action: Report message as [not]spam.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _changed(), _generateDeleteResult(), and
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'spam' - (integer) 1 to mark as spam, 0 to mark as innocent.
+ * 'uid' - (string) Indices of the messages to report (IMAP sequence
+ * string).
+ * </pre>
+ *
+ * @return mixed False on failure, or an object (see
+ * _generateDeleteResult() for format).
+ */
+ public function ReportSpam($vars)
+ {
+ $change = $this->_changed($vars, false);
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ $result = false;
+
+ if (IMP_Spam::reportSpam($indices, $vars->spam ? 'spam' : 'notspam')) {
+ $result = $this->_generateDeleteResult($vars, $indices, $change);
+ /* If result of reportSpam() is non-zero, then we know the message
+ * has been removed from the current mailbox. */
+ $result->deleted->remove = 1;
+ } elseif (!is_null($change)) {
+ $result = $this->_checkUidvalidity($vars);
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Blacklist/whitelist addresses from messages.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _changed(), _generateDeleteResult(), and
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'blacklist' - (integer) 1 to blacklist, 0 to whitelist.
+ * 'uid' - (string) Indices of the messages to report (IMAP sequence
+ * string).
+ * </pre>
+ *
+ * @return mixed False on failure, or an object (see
+ * _generateDeleteResult() for format).
+ */
+ public function Blacklist($vars)
+ {
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ if (empty($indices)) {
+ return false;
+ }
+
+ $imp_filter = new IMP_Filter();
+ $result = false;
+
+ if ($vars->blacklist) {
+ $change = $this->_changed($vars, false);
+ if (!is_null($change)) {
+ try {
+ if ($imp_filter->blacklistMessage($indices, false)) {
+ $result = $this->_generateDeleteResult($vars, $indices, $change);
+ }
+ } catch (Horde_Exception $e) {
+ $result = $this->_checkUidvalidity($vars);
+ }
+ }
+ } else {
+ try {
+ $imp_filter->whitelistMessage($indices, false);
+ } catch (Horde_Exception $e) {
+ $result = $this->_checkUidvalidity($vars);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Generate data necessary to display preview message.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'uid' - (string) Index of the messages to preview (IMAP sequence
+ * string) - must be single index.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the keys defined
+ * in IMP_View_ShowMessage::showMessage().
+ */
+ public function ShowPreview($vars)
+ {
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ if (count($indices) != 1) {
+ return false;
+ }
+
+ $ptr = each($indices);
+ $args = array(
+ 'mailbox' => $ptr['key'],
+ 'preview' => true,
+ 'uid' => intval(reset($ptr['value']))
+ );
+
+ try {
+ /* 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. */
+ $GLOBALS['imp_imap']->ob()->openMailbox($ptr['key'], Horde_Imap_Client::OPEN_READWRITE);
+ $show_msg = new IMP_Views_ShowMessage();
+ $result = (object)$show_msg->showMessage($args);
+ if (isset($result->error)) {
+ $result = $this->_checkUidvalidity($vars, $result);
+ }
+ } catch (Horde_Imap_Client_Exception $e) {
+ $result = new stdClass;
+ $result->error = $e->getMessage();
+ $result->errortype = 'horde.error';
+ $result->mailbox = $args['mailbox'];
+ $result->uid = $args['uid'];
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Convert HTML to text.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'text' - (string) The text to convert.
+ * </pre>
+ *
+ * @return object An object with the following entries:
+ * <pre>
+ * 'text' - (string) The converted text.
+ * </pre>
+ */
+ public function Html2Text($vars)
+ {
+ $result = new stdClass;
+ // Need to replace line endings or else IE won't display line endings
+ // properly.
+ $result->text = str_replace("\n", "\r\n", Horde_Text_Filter::filter($vars->text, 'html2text', array('charset' => Horde_Nls::getCharset())));
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Convert text to HTML.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'text' - (string) The text to convert.
+ * </pre>
+ *
+ * @return object An object with the following entries:
+ * <pre>
+ * 'text' - (string) The converted text.
+ * </pre>
+ */
+ public function Text2Html($vars)
+ {
+ $result = new stdClass;
+ $result->text = Horde_Text_Filter::filter($vars->text, 'text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO_LINKURL, 'class' => null, 'callback' => null));
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Get forward compose data.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'imp_compose' - (string) The IMP_Compose cache identifier.
+ * 'uid' - (string) Indices of the messages to forward (IMAP sequence
+ * string).
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'body' - (string) The body text of the message.
+ * 'format' - (string) Either 'text' or 'html'.
+ * 'fwd_list' - (array) See IMP_Dimp::getAttachmentInfo().
+ * 'header' - (array) The headers of the message.
+ * 'identity' - (integer) The identity ID to use for this message.
+ * 'imp_compose'- (string) The IMP_Compose cache identifier.
+ * 'ViewPort' - (object) See _viewPortData().
+ * </pre>
+ */
+ public function GetForwardData($vars)
+ {
+ $header = array();
+ $msg = $header = null;
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+
+ $i = each($indices);
+ $idx_string = reset($i['value']) . IMP::IDX_SEP . $i['key'];
+
+ try {
+ $imp_contents = IMP_Contents::singleton($idx_string);
+ $imp_compose = IMP_Compose::singleton($vars->imp_compose);
+ $imp_ui = new IMP_Ui_Compose();
+ $fwd_msg = $imp_ui->getForwardData($imp_compose, $imp_contents, $idx_string);
+ $header = $fwd_msg['headers'];
+ $header['replytype'] = 'forward';
+
+ $result = new stdClass;
+ /* Can't open session read-only since we need to store the message
+ * cache id. */
+ $result->imp_compose = $imp_compose->getCacheId();
+ $result->fwd_list = IMP_Dimp::getAttachmentInfo($imp_compose);
+ $result->body = $fwd_msg['body'];
+ $result->header = $header;
+ $result->format = $fwd_msg['format'];
+ $result->identity = $fwd_msg['identity'];
+ } catch (Horde_Exception $e) {
+ $GLOBALS['notification']->push($e, 'horde.error');
+ $result = $this->_checkUidvalidity($vars);
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Get reply data.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _checkUidvalidity(). Additional variables
+ * used:
+ * <pre>
+ * 'imp_compose' - (string) The IMP_Compose cache identifier.
+ * 'type' - (string) See IMP_Compose::replyMessage().
+ * 'uid' - (string) Indices of the messages to reply to (IMAP sequence
+ * string).
+ * </pre>
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'body' - (string) The body text of the message.
+ * 'format' - (string) Either 'text' or 'html'.
+ * 'header' - (array) The headers of the message.
+ * 'identity' - (integer) The identity ID to use for this message.
+ * 'imp_compose'- (string) The IMP_Compose cache identifier.
+ * 'ViewPort' - (object) See _viewPortData().
+ * </pre>
+ */
+ public function GetReplyData($vars)
+ {
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ $i = each($indices);
+ $idx_string = reset($i['value']) . IMP::IDX_SEP . $i['key'];
+
+ try {
+ $imp_contents = IMP_Contents::singleton($idx_string);
+ $imp_compose = IMP_Compose::singleton($vars->imp_compose);
+ $reply_msg = $imp_compose->replyMessage($vars->type, $imp_contents);
+ $header = $reply_msg['headers'];
+ $header['replytype'] = 'reply';
+
+ $result = new stdClass;
+ $result->imp_compose = $imp_compose->getCacheId();
+ $result->format = $reply_msg['format'];
+ $result->body = $reply_msg['body'];
+ $result->header = $header;
+ $result->identity = $reply_msg['identity'];
+ } catch (Horde_Exception $e) {
+ $GLOBALS['notification']->push($e, 'horde.error');
+ $result = $this->_checkUidvalidity($vars);
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Cancel compose.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'imp_compose' - (string) The IMP_Compose cache identifier.
+ * </pre>
+ *
+ * @return boolean True.
+ */
+ public function CancelCompose($vars)
+ {
+ $imp_compose = IMP_Compose::singleton($vars->imp_compose);
+ $imp_compose->destroy(false);
+
+ return true;
+ }
+
+ /**
+ * AJAX action: Delete a draft.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'imp_compose' - (string) The IMP_Compose cache identifier.
+ * </pre>
+ *
+ * @return boolean True.
+ */
+ public function DeleteDraft($vars)
+ {
+ $imp_compose = IMP_Compose::singleton($vars->imp_compose);
+ $imp_compose->destroy(false);
+
+ if ($draft_uid = $imp_compose->getMetadata('draft_uid')) {
+ $imp_message = IMP_Message::singleton();
+ $idx_array = array($draft_uid . IMP::IDX_SEP . IMP::folderPref($GLOBALS['prefs']->getValue('drafts_folder'), true));
+ $imp_message->delete($idx_array, array('nuke' => true));
+ }
+
+ return true;
+ }
+
+ /**
+ * AJAX action: Delete an attachment from compose data.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'atc_indices' - (string) Attachment IDs to delete.
+ * 'imp_compose' - (string) The IMP_Compose cache identifier.
+ * </pre>
+ *
+ * @return boolean True.
+ */
+ public function DeleteAttach($vars)
+ {
+ if ($vars->atc_indices) {
+ $imp_compose = IMP_Compose::singleton($vars->imp_compose);
+ foreach ($imp_compose->deleteAttachment($vars->atc_indices) as $val) {
+ $GLOBALS['notification']->push(sprintf(_("Deleted attachment \"%s\"."), Horde_Mime::decode($val)), 'horde.success');
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * AJAX action: Generate data necessary to display preview message.
+ *
+ * @param Horde_Variables $vars Variables used: NONE.
+ *
+ * @return mixed False on failure, or an object with the following
+ * entries:
+ * <pre>
+ * 'linkTags' - (array) TODO
+ * 'portal' - (string) The portal HTML data.
+ * </pre>
+ */
+ public function ShowPortal($vars)
+ {
+ // Load the block list. Blocks are located in $dimp_block_list.
+ // KEY: Block label; VALUE: Horde_Block object
+ require IMP_BASE . '/config/portal.php';
+
+ $blocks = $linkTags = array();
+ $css_load = array('imp' => true);
+
+ foreach ($dimp_block_list as $title => $block) {
+ if ($block['ob'] instanceof Horde_Block) {
+ $app = $block['ob']->getApp();
+ // TODO: Fix CSS.
+ $content = $block['ob']->getContent();
+ $css_load[$app] = true;
+ // Don't do substitutions on our own blocks.
+ if ($app != 'imp') {
+ $content = preg_replace('/<a href="([^"]+)"/',
+ '<a onclick="DimpBase.go(\'app:' . $app . '\', \'$1\');return false"',
+ $content);
+ if (preg_match_all('/<link .*?rel="stylesheet".*?\/>/',
+ $content, $links)) {
+ $content = str_replace($links[0], '', $content);
+ foreach ($links[0] as $link) {
+ if (preg_match('/href="(.*?)"/', $link, $href)) {
+ $linkOb = new stdClass;
+ $linkOb->href = $href[1];
+ if (preg_match('/media="(.*?)"/', $link, $media)) {
+ $linkOb->media = $media[1];
+ }
+ $linkTags[] = $linkOb;
+ }
+ }
+ }
+ }
+ if (!empty($content)) {
+ $entry = array(
+ 'app' => $app,
+ 'content' => $content,
+ 'title' => $title,
+ 'class' => empty($block['class']) ? 'headerbox' : $block['class'],
+ );
+ if (!empty($block['domid'])) {
+ $entry['domid'] = $block['domid'];
+ }
+ if (!empty($block['tag'])) {
+ $entry[$block['tag']] = true;
+ }
+ $blocks[] = $entry;
+ }
+ }
+ }
+
+ $result = new stdClass;
+ $result->portal = '';
+ if (!empty($blocks)) {
+ $t = new Horde_Template(IMP_TEMPLATES . '/imp/');
+ $t->set('block', $blocks);
+ $result->portal = $t->fetch('portal.html');
+ }
+ $result->linkTags = $linkTags;
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Purge deleted messages.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _changed(), and _generateDeleteResult().
+ * Additional variables used:
+ * <pre>
+ * 'uid' - (string) Indices of the messages to purge (IMAP sequence
+ * string).
+ * 'view' - (string) The current full mailbox.
+ * </pre>
+ *
+ * @return mixed False on failure, or an object (see
+ * _generateDeleteResult() for format).
+ */
+ public function PurgeDeleted($vars)
+ {
+ $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($vars->uid);
+ $change = $this->_changed($vars, $indices);
+
+ if (is_null($change)) {
+ return false;
+ }
+
+ if (!$change) {
+ $sort = IMP::getSort($vars->view);
+ $change = ($sort['by'] == Horde_Imap_Client::SORT_THREAD);
+ }
+
+ $imp_message = IMP_Message::singleton();
+ $expunged = $imp_message->expungeMailbox(array($vars->view => 1), array('list' => true));
+
+ if (empty($expunged[$mbox])) {
+ return false;
+ }
+
+ $expunge_count = count($expunged[$mbox]);
+ $display_folder = IMP::displayFolder($mbox);
+ if ($expunge_count == 1) {
+ $GLOBALS['notification']->push(sprintf(_("1 message was purged from \"%s\"."), $display_folder), 'horde.success');
+ } else {
+ $GLOBALS['notification']->push(sprintf(_("%s messages were purged from \"%s\"."), $expunge_count, $display_folder), 'horde.success');
+ }
+ $result = $this->_generateDeleteResult($vars, $expunged, $change);
+
+ /* Need to manually set remove to true since we want to remove message
+ * from the list no matter the current pref settings. */
+ $result->deleted->remove = 1;
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Send a Message Disposition Notification (MDN).
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'uid' - (string) Indices of the messages to isend MDN for (IMAP sequence
+ * string).
+ * 'view' - (string) The current full mailbox.
+ * </pre>
+ *
+ * @return boolean True on success, false on failure.
+ */
+ public function SendMDN($vars)
+ {
+ if (!$vars->view || !$vars->uid) {
+ return false;
+ }
+
+ try {
+ $fetch_ret = $GLOBALS['imp_imap']->ob()->fetch($vars->view, array(
+ Horde_Imap_Client::FETCH_HEADERTEXT => array(array('parse' => true, 'peek' => false))
+ ), array('ids' => array($vars->uid)));
+ } catch (Horde_Imap_Client_Exception $e) {
+ return false;
+ }
+
+ $imp_ui = new IMP_Ui_Message();
+ $imp_ui->MDNCheck($vars->view, $vars->uid, reset($fetch_ret[$vars->uid]['headertext']), true);
+
+ return true;
+ }
+
+ /**
+ * AJAX action: Process a user-supplied PGP symmetric passphrase.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'dialog_input' - (string) Input from the dialog screen.
+ * 'symmetricid' - (string) The symmetric ID to process.
+ * </pre>
+ *
+ * @return object An object with the following entries:
+ * <pre>
+ * 'error' - (string) An error message.
+ * 'success' - (integer) 1 on success, 0 on failure.
+ * </pre>
+ */
+ public function PGPSymmetric($vars)
+ {
+ $result = new stdClass;
+ $result->success = 0;
+
+ try {
+ $imp_pgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
+ Horde::requireSecureConnection();
+ if ($vars->dialog_input) {
+ if ($imp_pgp->storePassphrase('symmetric', $vars->dialog_input, $vars->symmetricid)) {
+ $result->success = 1;
+ } else {
+ $result->error = _("Invalid passphrase entered.");
+ }
+ } else {
+ $result->error = _("No passphrase entered.");
+ }
+ } catch (Horde_Exception $e) {
+ $result->error = $e->getMessage();
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Process a user-supplied passphrase for the PGP personal
+ * key.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'dialog_input' - (string) Input from the dialog screen.
+ * </pre>
+ *
+ * @return object An object with the following entries:
+ * <pre>
+ * 'error' - (string) An error message.
+ * 'success' - (integer) 1 on success, 0 on failure.
+ * </pre>
+ */
+ public function PGPPersonal($vars)
+ {
+ $result = new stdClass;
+ $result->success = false;
+
+ try {
+ $imp_pgp = Horde_Crypt::singleton(array('IMP', 'Pgp'));
+ Horde::requireSecureConnection();
+ if ($vars->dialog_input) {
+ if ($imp_pgp->storePassphrase('personal', $vars->dialog_input)) {
+ $result->success = 1;
+ } else {
+ $result->error = _("Invalid passphrase entered.");
+ }
+ } else {
+ $result->error = _("No passphrase entered.");
+ }
+ } catch (Horde_Exception $e) {
+ $result->error = $e->getMessage();
+ }
+
+ return $result;
+ }
+
+ /**
+ * AJAX action: Process a user-supplied passphrase for the S/MIME
+ * personal key.
+ *
+ * @param Horde_Variables $vars Variables used:
+ * <pre>
+ * 'dialog_input' - (string) Input from the dialog screen.
+ * </pre>
+ *
+ * @return object An object with the following entries:
+ * <pre>
+ * 'error' - (string) An error message.
+ * 'success' - (integer) 1 on success, 0 on failure.
+ * </pre>
+ */
+ public function SMIMEPersonal($vars)
+ {
+ $result = new stdClass;
+ $result->success = false;
+
+ try {
+ $imp_smime = Horde_Crypt::singleton(array('IMP', 'Smime'));
+ Horde::requireSecureConnection();
+ if ($vars->dialog_input) {
+ if ($imp_smime->storePassphrase($vars->dialog_input)) {
+ $result->success = 1;
+ } else {
+ $result->error = _("Invalid passphrase entered.");
+ }
+ } else {
+ $result->error = _("No passphrase entered.");
+ }
+ } catch (Horde_Exception $e) {
+ $result->error = $e->getMessage();
+ }
+
+ return $result;
+ }
+
+ /**
+ * Check the UID validity of the mailbox.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _viewPortData().
+ *
+ * @return mixed The JSON result, possibly with ViewPort information
+ * added if UID validity has changed.
+ */
+ protected function _checkUidvalidity($vars, $result = false)
+ {
+ try {
+ $GLOBALS['imp_imap']->checkUidvalidity($vars->view);
+ } catch (Horde_Exception $e) {
+ if (!is_object($result)) {
+ $result = new stdClass;
+ }
+ $result->ViewPort = $this->_viewPortData($vars, true);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Generates the delete data needed for DimpBase.js.
+ *
+ * @param Horde_Variables $vars See the list of variables needed for
+ * _viewPortData().
+ * @param array $indices The list of indices that were deleted.
+ * @param boolean $changed If true, add ViewPort information.
+ * @param boolean $nothread If true, don't do thread sort check.
+ *
+ * @return object An object with the following entries:
+ * <pre>
+ * 'deleted' - (object) See _generateDeleteResult().
+ * 'ViewPort' - (object) See _viewPortData().
+ * 'poll' - (array) Mailbox names as the keys, number of unseen messages
+ * as the values.
+ * </pre>
+ */
+ protected function _generateDeleteResult($vars, $indices, $change,
+ $nothread = false)
+ {
+ $imp_mailbox = IMP_Mailbox::singleton($vars->view);
+
+ $del = new stdClass;
+ $del->folder = $vars->view;
+ $del->uids = $GLOBALS['imp_imap']->ob()->utils->toSequenceString($indices, array('mailbox' => true));
+ $del->remove = intval($GLOBALS['prefs']->getValue('hide_deleted') ||
+ $GLOBALS['prefs']->getValue('use_trash'));
+ $del->cacheid = $imp_mailbox->getCacheID($vars->view);
+
+ $result = new stdClass;
+ $result->deleted = $del;
+
+ /* Check if we need to update thread information. */
+ if (!$change && !$nothread) {
+ $sort = IMP::getSort($vars->view);
+ $change = ($sort['by'] == Horde_Imap_Client::SORT_THREAD);
+ }
+
+ if ($change) {
+ $result->ViewPort = $this->_viewPortData($vars, true);
+ }
+
+ $poll = $this->_getPollInformation($vars->view);
+ if (!empty($poll)) {
+ $result->poll = $poll;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Determine if the cache information has changed.
+ *
+ * @param Horde_Variables $vars The following variables:
+ * <pre>
+ * 'cacheid' - (string) The browser (ViewPort) cache identifier.
+ * 'forceUpdate' - (integer) If 1, forces an update,
+ * 'view' - (string) The current ViewPort view (mailbox).
+ * </pre>
+ * @param boolean $rw Open mailbox as READ+WRITE?
+ *
+ * @return boolean True if the cache information has changed.
+ */
+ protected function _changed($vars, $rw = null)
+ {
+ /* Only update search mailboxes on forced refreshes. */
+ if ($GLOBALS['imp_search']->isSearchMbox($vars->view)) {
+ return ($this->_action == 'ViewPort') || $vars->forceUpdate;
+ }
+
+ /* 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) &&
+ !$GLOBALS['imp_search']->isSearchMbox($vars->view)) {
+ try {
+ $GLOBALS['imp_imap']->ob()->openMailbox($vars->view, $rw ? Horde_Imap_Client::OPEN_READWRITE : Horde_Imap_Client::OPEN_AUTO);
+ } catch (Horde_Imap_Client_Exception $e) {
+ $GLOBALS['notification']->push($e, 'horde.error');
+ return null;
+ }
+ }
+
+ $imp_mailbox = IMP_Mailbox::singleton($vars->view);
+ return ($imp_mailbox->getCacheID($vars->view) != $vars->cacheid);
+ }
+
+ /**
+ * Generate the information necessary for a ViewPort request from/to the
+ * browser.
+ *
+ * @param Horde_Variables $vars The following variables:
+ * <pre>
+ * TODO
+ * </pre>
+ * @param boolean $change True if cache information has changed.
+ *
+ * @return TODO
+ */
+ protected function _viewPortData($vars, $change)
+ {
+ $args = array(
+ 'applyfilter' => $vars->applyfilter,
+ 'cache' => $vars->cache,
+ 'cacheid' => $vars->cacheid,
+ 'change' => $change,
+ 'initial' => $vars->initial,
+ 'mbox' => $vars->view,
+ 'rangeslice' => $vars->rangeslice,
+ 'requestid' => $vars->requestid,
+ 'qsearch' => $vars->qsearch,
+ 'qsearchflag' => $vars->qsearchflag,
+ 'qsearchmbox' => $vars->qsearchmbox,
+ 'qsearchflagnot' => $vars->qsearchflagnot,
+ 'sortby' => $vars->sortby,
+ 'sortdir' => $vars->sortdir
+ );
+
+ if (!$vars->search || $args['initial']) {
+ $args += array(
+ 'after' => intval($vars->after),
+ 'before' => intval($vars->before)
+ );
+ }
+
+ if (!$vars->search) {
+ list($slice_start, $slice_end) = explode(':', $vars->slice, 2);
+ $args += array(
+ 'slice_start' => intval($slice_start),
+ 'slice_end' => intval($slice_end)
+ );
+ } else {
+ $search = Horde_Serialize::unserialize($vars->search, Horde_Serialize::JSON);
+ $args += array(
+ 'search_uid' => isset($search->imapuid) ? $search->imapuid : null,
+ 'search_unseen' => isset($search->unseen) ? $search->unseen : null
+ );
+ }
+
+ $list_msg = new IMP_Views_ListMessages();
+ return $list_msg->listMessages($args);
+ }
+
+ /**
+ * Generate poll information for a single mailbox.
+ *
+ * @param string $mbox The full mailbox name.
+ *
+ * @return array Key is the mailbox name, value is the number of unseen
+ * messages.
+ */
+ protected function _getPollInformation($mbox)
+ {
+ $imptree = IMP_Imap_Tree::singleton();
+ $elt = $imptree->get($mbox);
+ if (!$imptree->isPolled($elt)) {
+ return array();
+ }
+
+ $info = $imptree->getElementInfo($mbox);
+ return array($mbox => isset($info['unseen']) ? intval($info['unseen']) : 0);
+ }
+
+ /**
+ * Generate quota information.
+ *
+ * @return array 'p': Quota percentage; 'm': Quota message
+ */
+ protected function _getQuota()
+ {
+ if (isset($_SESSION['imp']['quota']) &&
+ is_array($_SESSION['imp']['quota'])) {
+ $quotadata = IMP::quotaData(false);
+ if (!empty($quotadata)) {
+ return array('p' => round($quotadata['percent']), 'm' => $quotadata['message']);
+ }
+ }
+
+ return null;
+ }
+
+}
'password' => true,
'text' => $text,
'type' => $type,
- 'uri' => Horde::applicationUrl('ajax.php', true, -1) . '/' . $type
+ 'uri' => Horde::getServiceLink('ajax', 'imp') . '/' . $type
);
return 'IMPDialog.display(' . Horde::escapeJson($js_params, array('urlencode' => true)) . ')';
/* Variables used in core javascript files. */
$code['conf'] = array_filter(array(
// URL variables
- 'URI_AJAX' => (string) Horde::applicationUrl('ajax.php'),
+ 'URI_AJAX' => (string) Horde::getServiceLink('ajax', 'imp'),
'URI_COMPOSE' => (string) Horde::applicationUrl('compose-dimp.php'),
'URI_DIMP' => (string) Horde::applicationUrl('index-dimp.php'),
'URI_MESSAGE' => (string) Horde::applicationUrl('message-dimp.php'),
+++ /dev/null
-<?php
-/**
- * Performs the AJAX-requested action.
- *
- * Copyright 2005-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author Michael Slusarz <slusarz@horde.org>
- * @author Jan Schneider <jan@horde.org>
- * @author Gonçalo Queirós <mail@goncaloqueiros.net>
- * @package Kronolith
- */
-
-function getDriver($cal)
-{
- list($driver, $calendar) = explode('|', $cal);
- if ($driver == 'internal' &&
- !array_key_exists($calendar,
- Kronolith::listCalendars(false, Horde_Perms::SHOW))) {
- $GLOBALS['notification']->push(_("Permission Denied"), 'horde.error');
- return false;
- }
- $kronolith_driver = Kronolith::getDriver($driver, $calendar);
- if ($kronolith_driver instanceof PEAR_Error) {
- $GLOBALS['notification']->push($kronolith_driver, 'horde.error');
- return false;
- }
- if ($driver == 'remote') {
- $kronolith_driver->setParam('timeout', 15);
- }
- return $kronolith_driver;
-}
-
-function saveEvent($event)
-{
- $result = $event->save();
- if ($result instanceof PEAR_Error) {
- $GLOBALS['notification']->push($result, 'horde.error');
- return true;
- }
- $start = new Horde_Date(Horde_Util::getFormData('view_start'));
- $end = new Horde_Date(Horde_Util::getFormData('view_end'));
- $end->hour = 23;
- $end->min = $end->sec = 59;
- Kronolith::addEvents($events, $event, $start, $end, true, true);
- $result = new stdClass;
- $result->cal = $event->calendarType . '|' . $event->calendar;
- $result->view = Horde_Util::getFormData('view');
- $result->sig = $start->dateString() . $end->dateString();
- if (count($events)) {
- $result->events = $events;
- }
- return $result;
-}
-
-require_once dirname(__FILE__) . '/lib/Application.php';
-$action = basename(Horde_Util::getPathInfo());
-if (empty($action)) {
- // This is the only case where we really don't return anything, since
- // the frontend can be presumed not to make this request on purpose.
- // Other missing data cases we return a response of boolean false.
- exit;
-}
-
-// The following actions do not need write access to the session and
-// should be opened read-only for performance reasons.
-$session_control = null;
-if (in_array($action, array())) {
- $session_control = 'readonly';
-}
-
-try {
- Horde_Registry::appInit('kronolith', array('authentication' => 'throw', 'session_control' => $session_control));
-} catch (Horde_Exception $e) {
- /* Handle session timeouts when they come from an AJAX request. */
- if (($e->getCode() == Horde_Registry::AUTH_FAILURE) &&
- ($action != 'LogOut')) {
- $notification = Horde_Notification::singleton();
- $k_notify = $notification->attach('status', array(), 'Kronolith_Notification_Listener_Status');
- $notification->push(str_replace('&', '&', Horde_Auth::getLogoutUrl(array('reason' => Horde_Auth::REASON_SESSION))), 'kronolith.timeout', array('content.raw'));
- Horde::sendHTTPResponse(Horde::prepareResponse(null, $k_notify), 'json');
- exit;
- }
-
- Horde_Auth::authenticateFailure('kronolith', $e);
-}
-
-// Process common request variables.
-$cacheid = Horde_Util::getPost('cacheid');
-
-// Open an output buffer to ensure that we catch errors that might break JSON
-// encoding.
-ob_start();
-
-try {
- $result = true;
-
- switch ($action) {
- case 'ListEvents':
- $start = new Horde_Date(Horde_Util::getFormData('start'));
- $end = new Horde_Date(Horde_Util::getFormData('end'));
- $cal = Horde_Util::getFormData('cal');
- $result = new stdClass;
- $result->cal = $cal;
- $result->view = Horde_Util::getFormData('view');
- $result->sig = $start->dateString() . $end->dateString();
- if (!($kronolith_driver = getDriver($cal))) {
- break;
- }
- $events = $kronolith_driver->listEvents($start, $end, true, false, true);
- if ($events instanceof PEAR_Error) {
- $notification->push($events, 'horde.error');
- break;
- }
- if (count($events)) {
- $result->events = $events;
- }
- break;
-
- case 'GetEvent':
- if (!($kronolith_driver = getDriver(Horde_Util::getFormData('cal')))) {
- break;
- }
- if (is_null($id = Horde_Util::getFormData('id'))) {
- break;
- }
- $event = $kronolith_driver->getEvent($id, Horde_Util::getFormData('date'));
- if ($event instanceof PEAR_Error) {
- $notification->push($event, 'horde.error');
- break;
- }
- if (!$event) {
- $notification->push(_("The requested event was not found."), 'horde.error');
- break;
- }
- $result = new stdClass;
- $result->event = $event->toJson(null, true, $prefs->getValue('twentyFour') ? 'H:i' : 'h:i A');
- break;
-
- case 'SaveEvent':
- if (!($kronolith_driver = getDriver(Horde_Util::getFormData('targetcalendar')))) {
- break;
- }
- $event = $kronolith_driver->getEvent(Horde_Util::getFormData('id'));
- if ($event instanceof PEAR_Error) {
- $notification->push($event, 'horde.error');
- break;
- }
- if (!$event) {
- $notification->push(_("The requested event was not found."), 'horde.error');
- break;
- }
- if (!$event->hasPermission(Horde_Perms::EDIT)) {
- $notification->push(_("You do not have permission to edit this event."), 'horde.warning');
- break;
- }
- $event->readForm();
- $result = saveEvent($event);
- if ($result !== true && Horde_Util::getFormData('sendupdates')) {
- Kronolith::sendITipNotifications($event, $notification, Kronolith::ITIP_REQUEST);
- }
- break;
-
- case 'QuickSaveEvent':
- $kronolith_driver = Kronolith::getDriver();
- try {
- $event = Kronolith::quickAdd(Horde_Util::getFormData('text'),
- Kronolith::getDefaultCalendar(Horde_Perms::EDIT));
- if ($event instanceof PEAR_Error) {
- $notification->push($event, 'horde.error');
- break;
- }
- $result = saveEvent($event);
- } catch (Horde_Exception $e) {
- $notification->push($e);
- }
- break;
-
- case 'UpdateEvent':
- if (!($kronolith_driver = getDriver(Horde_Util::getFormData('cal')))) {
- break;
- }
- if (is_null($id = Horde_Util::getFormData('id'))) {
- break;
- }
- $event = $kronolith_driver->getEvent($id);
- if ($event instanceof PEAR_Error) {
- $notification->push($event, 'horde.error');
- break;
- }
- if (!$event) {
- $notification->push(_("The requested event was not found."), 'horde.error');
- break;
- }
- if (!$event->hasPermission(Horde_Perms::EDIT)) {
- $notification->push(_("You do not have permission to edit this event."), 'horde.warning');
- break;
- }
- $attributes = Horde_Serialize::unserialize(Horde_Util::getFormData('att'), Horde_Serialize::JSON);
- foreach ($attributes as $attribute => $value) {
- switch ($attribute) {
- case 'start_date':
- $start = new Horde_Date($value);
- $event->start->year = $start->year;
- $event->start->month = $start->month;
- $event->start->mday = $start->mday;
- $event->end = $event->start->add(array('min' => $event->durMin));
- break;
-
- case 'start':
- $event->start = new Horde_Date($value);
- break;
-
- case 'end':
- $event->end = new Horde_Date($value);
- if ($event->end->hour == 23 &&
- $event->end->min == 59 &&
- $event->end->sec == 59) {
- $event->end->mday++;
- $event->end->hour = $event->end->min = $event->end->sec = 0;
- }
- break;
-
- case 'offDays':
- $event->start->mday += $value;
- $event->end->mday += $value;
- break;
-
- case 'offMins':
- $event->start->min += $value;
- $event->end->min += $value;
- break;
- }
- }
- $result = saveEvent($event);
- break;
-
- case 'DeleteEvent':
- if (!($kronolith_driver = getDriver(Horde_Util::getFormData('cal')))) {
- break;
- }
- if (is_null($id = Horde_Util::getFormData('id'))) {
- break;
- }
- $event = $kronolith_driver->getEvent($id);
- if ($event instanceof PEAR_Error) {
- $notification->push($event, 'horde.error');
- break;
- }
- if (!$event) {
- $notification->push(_("The requested event was not found."), 'horde.error');
- break;
- }
- if (!$event->hasPermission(Horde_Perms::DELETE)) {
- $notification->push(_("You do not have permission to delete this event."), 'horde.warning');
- break;
- }
- $deleted = $kronolith_driver->deleteEvent($event->id);
- if ($deleted instanceof PEAR_Error) {
- $notification->push($deleted, 'horde.error');
- break;
- }
- if (Horde_Util::getFormData('sendupdates', false)) {
- Kronolith::sendITipNotifications($event, $notification, Kronolith::ITIP_CANCEL);
- }
- $result = new stdClass;
- $result->deleted = true;
- break;
-
- case 'SearchEvents':
- $query = Horde_Serialize::unserialize(Horde_Util::getFormData('query'), Horde_Serialize::JSON);
- if (!isset($query->start)) {
- $query->start = new Horde_Date($_SERVER['REQUEST_TIME']);
- }
- if (!isset($query->end)) {
- $query->end = null;
- }
- $cals = Horde_Serialize::unserialize(Horde_Util::getFormData('cals'), Horde_Serialize::JSON);
- $events = array();
- foreach ($cals as $cal) {
- if (!($kronolith_driver = getDriver($cal))) {
- break;
- }
- $result = $kronolith_driver->search($query, true);
- if ($result instanceof PEAR_Error) {
- $notification->push($result, 'horde.error');
- break;
- }
- if ($result) {
- $events[$cal] = $result;
- }
- }
- $result = new stdClass;
- $result->view = 'search';
- $result->query = Horde_Util::getFormData('query');
- if ($events) {
- $result->events = $events;
- }
- break;
-
- case 'ListTasks':
- if (!$registry->hasMethod('tasks/listTasks')) {
- break;
- }
-
- $tasklist = Horde_Util::getFormData('list');
- $tasktype = Horde_Util::getFormData('type');
- $tasks = $registry->call('tasks/listTasks',
- array(null, null, null, $tasklist, $tasktype == 'incomplete' ? 'future_incomplete' : $tasktype, true));
- if ($tasks instanceof PEAR_Error) {
- $notification->push($tasks, 'horde.error');
- break;
- }
-
- $result = new stdClass;
- $result->list = $tasklist;
- $result->type = $tasktype;
- $result->sig = Horde_Util::getFormData('sig');
- if (count($tasks)) {
- $result->tasks = $tasks;
- }
- break;
-
- case 'GetTask':
- if (!$registry->hasMethod('tasks/getTask')) {
- break;
- }
- if (is_null($id = Horde_Util::getFormData('id')) ||
- is_null($list = Horde_Util::getFormData('list'))) {
- break;
- }
- $task = $registry->tasks->getTask($list, $id);
- if ($task instanceof PEAR_Error) {
- $notification->push($task, 'horde.error');
- break;
- }
- if (!$task) {
- $notification->push(_("The requested task was not found."), 'horde.error');
- break;
- }
- $result = new stdClass;
- $result->task = $task->toJson(true, $prefs->getValue('twentyFour') ? 'H:i' : 'h:i A');
- break;
-
- case 'SaveTask':
- if (!$registry->hasMethod('tasks/updateTask') ||
- !$registry->hasMethod('tasks/addTask')) {
- break;
- }
-
- $id = Horde_Util::getFormData('task_id');
- $list = Horde_Util::getFormData('old_tasklist');
- $task = Horde_Util::getFormData('task');
-
- $due = trim($task['due_date'] . ' ' . $task['due_time']);
- if (!empty($due)) {
- // strptime() is locale dependent, i.e. %p is not always matching
- // AM/PM. Set the locale to C to workaround this, but grab the
- // locale's D_FMT before that.
- $date_format = Horde_Nls::getLangInfo(D_FMT);
- $old_locale = setlocale(LC_TIME, 0);
- setlocale(LC_TIME, 'C');
- $format = $date_format . ' '
- . ($prefs->getValue('twentyFour') ? '%H:%M' : '%I:%M %p');
-
- // Try exact format match first.
- if ($date_arr = strptime($due, $format)) {
- $task['due'] = new Horde_Date(
- array('year' => $date_arr['tm_year'] + 1900,
- 'month' => $date_arr['tm_mon'] + 1,
- 'mday' => $date_arr['tm_mday'],
- 'hour' => $date_arr['tm_hour'],
- 'min' => $date_arr['tm_min'],
- 'sec' => $date_arr['tm_sec']));
- } else {
- $task['due'] = new Horde_Date($due);
- }
- setlocale(LC_TIME, $old_locale);
- }
-
- if ($task['alarm']['on']) {
- $task['alarm'] = $task['alarm']['value'] * $task['alarm']['unit'];
- } else {
- $task['alarm'] = 0;
- }
-
- if ($id && $list) {
- $result = $registry->tasks->updateTask($list, $id, $task);
- } else {
- $result = $registry->tasks->addTask($task);
- }
- if ($result instanceof PEAR_Error) {
- $notification->push($result, 'horde.error');
- break;
- }
- if (!$id) {
- $id = $result[0];
- }
- $task = $registry->tasks->getTask($task['tasklist'], $id);
- if ($task instanceof PEAR_Error) {
- $notification->push($task, 'horde.error');
- break;
- }
- $result = new stdClass;
- $result->type = $task->completed ? 'complete' : 'incomplete';
- $result->list = $task->tasklist;
- $result->sig = Horde_Util::getFormData('sig');
- $result->tasks = array($id => $task->toJson(false, $prefs->getValue('twentyFour') ? 'H:i' : 'h:i A'));
- break;
-
- case 'DeleteTask':
- if (!$registry->hasMethod('tasks/deleteTask')) {
- break;
- }
- if (is_null($id = Horde_Util::getFormData('id')) ||
- is_null($list = Horde_Util::getFormData('list'))) {
- break;
- }
- $result = $registry->tasks->deleteTask($list, $id);
- if ($result instanceof PEAR_Error) {
- $notification->push($result, 'horde.error');
- break;
- }
- $result = new stdClass;
- $result->deleted = true;
- break;
-
- case 'ToggleCompletion':
- if (!$registry->hasMethod('tasks/toggleCompletion')) {
- break;
- }
- $tasklist = Horde_Util::getFormData('list');
- $taskid = Horde_Util::getFormData('id');
- $saved = $registry->call('tasks/toggleCompletion',
- array($taskid, $tasklist));
- if ($saved instanceof PEAR_Error) {
- $notification->push($saved, 'horde.error');
- break;
- }
-
- $result = new stdClass;
- $result->toggled = true;
- break;
-
- case 'ListTopTags':
- $tagger = new Kronolith_Tagger();
- $result = new stdClass;
- $result->tags = array();
- $tags = $tagger->getCloud(Horde_Auth::getAuth(), 10);
- foreach ($tags as $tag) {
- $result->tags[] = $tag['tag_name'];
- }
- break;
-
- case 'GetFreeBusy':
- $fb = Kronolith_FreeBusy::get(Horde_Util::getFormData('email'), true);
- if ($fb instanceof PEAR_Error) {
- $notification->push($fb->getMessage(), 'horde.warning');
- break;
- }
- $result = new stdClass;
- $result->fb = $fb;
- break;
-
- case 'SearchCalendars':
- $result = new stdClass;
- $result->events = 'Searched for calendars: ' . Horde_Util::getFormData('title');
- break;
-
- case 'SaveCalendar':
- $calendar_id = Horde_Util::getFormData('calendar');
- $result = new stdClass;
-
- switch (Horde_Util::getFormData('type')) {
- case 'internal':
- $info = array();
- foreach (array('name', 'color', 'description', 'tags') as $key) {
- $info[$key] = Horde_Util::getFormData($key);
- }
-
- // Create a calendar.
- if (!$calendar_id) {
- if (!Horde_Auth::getAuth() || $prefs->isLocked('default_share')) {
- break 2;
- }
- $calendar = Kronolith::addShare($info);
- if ($calendar instanceof PEAR_Error) {
- $notification->push($calendar, 'horde.error');
- break 2;
- }
- $notification->push(sprintf(_("The calendar \"%s\" has been created."), $info['name']), 'horde.success');
- $result->calendar = $calendar->getName();
- break;
- }
-
- // Update a calendar.
- $calendar = $kronolith_shares->getShare($calendar_id);
- if ($calendar instanceof PEAR_Error) {
- $notification->push($calendar, 'horde.error');
- break 2;
- }
- $original_name = $calendar->get('name');
- $updated = Kronolith::updateShare($calendar, $info);
- if ($updated instanceof PEAR_Error) {
- $notification->push($updated, 'horde.error');
- break 2;
- }
- if ($calendar->get('name') != $original_name) {
- $notification->push(sprintf(_("The calendar \"%s\" has been renamed to \"%s\"."), $original_name, $calendar->get('name')), 'horde.success');
- } else {
- $notification->push(sprintf(_("The calendar \"%s\" has been saved."), $original_name), 'horde.success');
- }
-
- break;
-
- case 'tasklists':
- $calendar = array();
- foreach (array('name', 'color', 'description') as $key) {
- $calendar[$key] = Horde_Util::getFormData($key);
- }
-
- // Create a task list.
- if (!$calendar_id) {
- if (!Horde_Auth::getAuth() || $prefs->isLocked('default_share')) {
- break 2;
- }
- $tasklist = $registry->tasks->addTasklist($calendar['name'], $calendar['description'], $calendar['color']);
- if ($tasklist instanceof PEAR_Error) {
- $notification->push($tasklist, 'horde.error');
- break 2;
- }
- $notification->push(sprintf(_("The task list \"%s\" has been created."), $calendar['name']), 'horde.success');
- $result->calendar = $tasklist;
- break;
- }
-
- // Update a task list.
- $calendar_id = substr($calendar_id, 6);
- $tasklists = $registry->tasks->listTasklists(true, Horde_Perms::EDIT);
- if (!isset($tasklists[$calendar_id])) {
- $notification->push(_("You are not allowed to change this task list."), 'horde.error');
- break 2;
- }
- $updated = $registry->tasks->updateTasklist($calendar_id, $calendar);
- if ($updated instanceof PEAR_Error) {
- $notification->push($updated, 'horde.error');
- break 2;
- }
- if ($tasklists[$calendar_id]->get('name') != $calendar['name']) {
- $notification->push(sprintf(_("The task list \"%s\" has been renamed to \"%s\"."), $tasklists[$calendar_id]->get('name'), $calendar['name']), 'horde.success');
- } else {
- $notification->push(sprintf(_("The task list \"%s\" has been saved."), $tasklists[$calendar_id]->get('name')), 'horde.success');
- }
-
- break;
-
- case 'remote':
- $calendar = array();
- foreach (array('name', 'description', 'url', 'color', 'username', 'password') as $key) {
- $calendar[$key] = Horde_Util::getFormData($key);
- }
- $subscribed = Kronolith::subscribeRemoteCalendar($calendar);
- if ($subscribed instanceof PEAR_Error) {
- $notification->push($subscribed, 'horde.error');
- break 2;
- }
- if ($calendar_id) {
- $notification->push(sprintf(_("The calendar \"%s\" has been saved."), $calendar['name']), 'horde.success');
- } else {
- $notification->push(sprintf(_("You have been subscribed to \"%s\" (%s)."), $calendar['name'], $calendar['url']), 'horde.success');
- }
- break;
- }
-
- $result->saved = true;
- $result->color = Kronolith::foregroundColor($calendar);
- break;
-
- case 'DeleteCalendar':
- $calendar_id = Horde_Util::getFormData('calendar');
-
- switch (Horde_Util::getFormData('type')) {
- case 'internal':
- $calendar = $kronolith_shares->getShare($calendar_id);
- if ($calendar instanceof PEAR_Error) {
- $notification->push($calendar, 'horde.error');
- break 2;
- }
- $deleted = Kronolith::deleteShare($calendar);
- if ($deleted instanceof PEAR_Error) {
- $notification->push(sprintf(_("Unable to delete \"%s\": %s"), $calendar->get('name'), $deleted->getMessage()), 'horde.error');
- break 2;
- }
- $notification->push(sprintf(_("The calendar \"%s\" has been deleted."), $calendar->get('name')), 'horde.success');
- break;
-
- case 'tasklists':
- $calendar_id = substr($calendar_id, 6);
- $tasklists = $registry->tasks->listTasklists(true);
- if (!isset($tasklists[$calendar_id])) {
- $notification->push(_("You are not allowed to delete this task list."), 'horde.error');
- break 2;
- }
- $deleted = $registry->tasks->deleteTasklist($calendar_id);
- if ($deleted instanceof PEAR_Error) {
- $notification->push(sprintf(_("Unable to delete \"%s\": %s"), $tasklists[$calendar_id]->get('name'), $deleted->getMessage()), 'horde.error');
- break 2;
- }
- $notification->push(sprintf(_("The task list \"%s\" has been deleted."), $tasklists[$calendar_id]->get('name')), 'horde.success');
- break;
-
- case 'remote':
- $deleted = Kronolith::unsubscribeRemoteCalendar($calendar_id);
- if ($deleted instanceof PEAR_Error) {
- $notification->push($deleted, 'horde.error');
- break 2;
- }
- $notification->push(sprintf(_("You have been unsubscribed from \"%s\" (%s)."), $deleted['name'], $deleted['url']), 'horde.success');
- break;
- }
-
- $result = new stdClass;
- $result->deleted = true;
- break;
-
- case 'GetRemoteInfo':
- $params = array();
- if ($user = Horde_Util::getFormData('username')) {
- $params['user'] = $user;
- $params['password'] = Horde_Util::getFormData('password');
- }
- if (!empty($GLOBALS['conf']['http']['proxy']['proxy_host'])) {
- $params['proxy'] = $GLOBALS['conf']['http']['proxy'];
- }
- $driver = Kronolith_Driver::factory('Ical', $params);
- $driver->open(Horde_Util::getFormData('url'));
- try {
- $ical = $driver->getRemoteCalendar(false);
- } catch (Kronolith_Exception $e) {
- if ($e->getCode() == 401) {
- $result = new stdClass;
- $result->auth = true;
- break;
- }
- throw $e;
- }
- $result = new stdClass;
- $result->success = true;
- $name = $ical->getAttribute('X-WR-CALNAME');
- if (!($name instanceof PEAR_Error)) {
- $result->name = $name;
- }
- $desc = $ical->getAttribute('X-WR-CALDESC');
- if (!($desc instanceof PEAR_Error)) {
- $result->desc = $desc;
- }
- break;
-
- case 'SaveCalPref':
- break;
-
- case 'ChunkContent':
- $chunk = basename(Horde_Util::getPost('chunk'));
- if (!empty($chunk)) {
- $result = new stdClass;
- $result->chunk = Horde_Util::bufferOutput('include', KRONOLITH_TEMPLATES . '/chunks/' . $chunk . '.php');
- }
- break;
-
- default:
- $notification->push('Unknown action ' . $action, 'horde.error');
- break;
- }
-} catch (Exception $e) {
- $notification->push($e->getMessage(), 'horde.error');
-}
-
-// Clear the output buffer that we started above, and log any unexpected
-// output at a DEBUG level.
-$errors = ob_get_clean();
-if ($errors) {
- Horde::logMessage('Kronolith: unexpected output: ' .
- $errors, __FILE__, __LINE__, PEAR_LOG_DEBUG);
-}
-
-// Send the final result.
-Horde::sendHTTPResponse(Horde::prepareResponse($result, $GLOBALS['kronolith_notify']), 'json');
msgs.find(function(m) {
switch (m.type) {
- case 'kronolith.timeout':
+ case 'horde.ajaxtimeout':
this.logout(Kronolith.conf.timeout_url);
return true;
--- /dev/null
+<?php
+/**
+ * Defines the AJAX interface for Kronolith.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @author Jan Schneider <jan@horde.org>
+ * @author Gonçalo Queirós <mail@goncaloqueiros.net>
+ * @package Kronolith
+ */
+class Kronolith_Ajax_Application extends Horde_Ajax_Application_Base
+{
+ /**
+ * Returns a notification handler object to use to output any
+ * notification messages triggered by the action.
+ *
+ * @return Horde_Notification_Handler_Base The notification handler.
+ */
+ public function notificationHandler()
+ {
+ return $GLOBALS['kronolith_notify'];
+ }
+
+ /**
+ * TODO
+ */
+ public function ListEvents($vars)
+ {
+ $start = new Horde_Date($vars->start);
+ $end = new Horde_Date($vars->end);
+
+ $result = new stdClass;
+ $result->cal = $vars->cal;
+ $result->view = $vars->view;
+ $result->sig = $start->dateString() . $end->dateString();
+ if (!($kronolith_driver = $this->_getDriver($vars->cal))) {
+ return $result;
+ }
+ $events = $kronolith_driver->listEvents($start, $end, true, false, true);
+ if ($events instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($events, 'horde.error');
+ return $result;
+ break;
+ }
+
+ if (count($events)) {
+ $result->events = $events;
+ }
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function GetEvent($vars)
+ {
+ if (!($kronolith_driver = $this->_getDriver($vars->cal)) ||
+ !isset($vars->id)) {
+ return false;
+ }
+
+ $event = $kronolith_driver->getEvent($vars->id, $vars->date);
+ if (!$event) {
+ $GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
+ return false;
+ } elseif ($event instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($event, 'horde.error');
+ return false;
+ }
+
+ $result = new stdClass;
+ $result->event = $event->toJson(null, true, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A');
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function SaveEvent($vars)
+ {
+ if (!($kronolith_driver = $this->_getDriver($vars->targetcalendar))) {
+ return false;
+ }
+
+ $event = $kronolith_driver->getEvent($vars->id);
+ if (!$event) {
+ $GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
+ return false;
+ } elseif ($event instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($event, 'horde.error');
+ return false;
+ } elseif (!$event->hasPermission(Horde_Perms::EDIT)) {
+ $notification->push(_("You do not have permission to edit this event."), 'horde.warning');
+ return false;
+ }
+
+ $event->readForm();
+ $result = $this->_saveEvent($event);
+ if (($result !== true) && $vars->sendupdates) {
+ Kronolith::sendITipNotifications($event, $GLOBALS['notification'], Kronolith::ITIP_REQUEST);
+ }
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function QuickSaveEvent($vars)
+ {
+ $kronolith_driver = Kronolith::getDriver();
+ try {
+ $event = Kronolith::quickAdd($vars->text, Kronolith::getDefaultCalendar(Horde_Perms::EDIT));
+ if ($event instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($event, 'horde.error');
+ return false;
+ }
+ return $this->_saveEvent($event);
+ } catch (Horde_Exception $e) {
+ $GLOBALS['notification']->push($e);
+ return false;
+ }
+ }
+
+ /**
+ * TODO
+ */
+ public function UpdateEvent($vars)
+ {
+ if (!($kronolith_driver = $this->_getDriver($vars->cal)) ||
+ !isset($vars->id)) {
+ return false;
+ }
+
+ $event = $kronolith_driver->getEvent($vars->id);
+ if (!$event) {
+ $GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
+ return false;
+ } elseif ($event instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($event, 'horde.error');
+ return false;
+ } elseif (!$event->hasPermission(Horde_Perms::EDIT)) {
+ $GLOBALS['notification']->push(_("You do not have permission to edit this event."), 'horde.warning');
+ return false;
+ }
+
+ $attributes = Horde_Serialize::unserialize($vars->att, Horde_Serialize::JSON);
+ foreach ($attributes as $attribute => $value) {
+ switch ($attribute) {
+ case 'start_date':
+ $start = new Horde_Date($value);
+ $event->start->year = $start->year;
+ $event->start->month = $start->month;
+ $event->start->mday = $start->mday;
+ $event->end = $event->start->add(array('min' => $event->durMin));
+ break;
+
+ case 'start':
+ $event->start = new Horde_Date($value);
+ break;
+
+ case 'end':
+ $event->end = new Horde_Date($value);
+ if ($event->end->hour == 23 &&
+ $event->end->min == 59 &&
+ $event->end->sec == 59) {
+ $event->end->mday++;
+ $event->end->hour = $event->end->min = $event->end->sec = 0;
+ }
+ break;
+
+ case 'offDays':
+ $event->start->mday += $value;
+ $event->end->mday += $value;
+ break;
+
+ case 'offMins':
+ $event->start->min += $value;
+ $event->end->min += $value;
+ break;
+ }
+ }
+
+ return $this->_saveEvent($event);
+ }
+
+ /**
+ * TODO
+ */
+ public function DeleteEvent($vars)
+ {
+ if (!($kronolith_driver = $this->_getDriver($vars->cal)) ||
+ !isset($vars->id)) {
+ return false;
+ }
+
+ $event = $kronolith_driver->getEvent($id);
+ if (!$event) {
+ $GLOBALS['notification']->push(_("The requested event was not found."), 'horde.error');
+ return false;
+ } elseif ($event instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($event, 'horde.error');
+ return false;
+ } elseif (!$event->hasPermission(Horde_Perms::DELETE)) {
+ $GLOBALS['notification']->push(_("You do not have permission to delete this event."), 'horde.warning');
+ return false;
+ }
+
+ $deleted = $kronolith_driver->deleteEvent($event->id);
+ if ($deleted instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($deleted, 'horde.error');
+ return false;
+ }
+
+ if ($vars->sendupdates) {
+ Kronolith::sendITipNotifications($event, $GLOBALS['notification'], Kronolith::ITIP_CANCEL);
+ }
+
+ $result = new stdClass;
+ $result->deleted = true;
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function SearchEvents($vars)
+ {
+ $query = Horde_Serialize::unserialize($vars->query, Horde_Serialize::JSON);
+ if (!isset($query->start)) {
+ $query->start = new Horde_Date($_SERVER['REQUEST_TIME']);
+ }
+ if (!isset($query->end)) {
+ $query->end = null;
+ }
+
+ $cals = Horde_Serialize::unserialize($vars->cals, Horde_Serialize::JSON);
+ $events = array();
+ foreach ($cals as $cal) {
+ if (!($kronolith_driver = $this->_getDriver($cal))) {
+ break;
+ }
+ $result = $kronolith_driver->search($query, true);
+ if ($result instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($result, 'horde.error');
+ break;
+ }
+ if ($result) {
+ $events[$cal] = $result;
+ }
+ }
+
+ $result = new stdClass;
+ $result->view = 'search';
+ $result->query = $vars->query;
+ if ($events) {
+ $result->events = $events;
+ }
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function ListTasks($vars)
+ {
+ if (!$GLOBALS['registry']->hasMethod('tasks/listTasks')) {
+ return false;
+ }
+
+ $tasks = $GLOBALS['registry']->call('tasks/listTasks', array(null, null, null, $vars->list, $vars->type == 'incomplete' ? 'future_incomplete' : $vars->type, true));
+ if ($tasks instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($tasks, 'horde.error');
+ return false;
+ }
+
+ $result = new stdClass;
+ $result->list = $vars->list;
+ $result->type = $vars->type;
+ $result->sig = $vars->sig;
+ if (count($tasks)) {
+ $result->tasks = $tasks;
+ }
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function GetTask($vars)
+ {
+ if (!$GLOBALS['registry']->hasMethod('tasks/getTask') ||
+ !isset($vars->id) ||
+ !isset($vars->list)) {
+ return false;
+ }
+
+ $task = $registry->tasks->getTask($vars->list, $vars->id);
+ if (!$task) {
+ $GLOBALS['notification']->push(_("The requested task was not found."), 'horde.error');
+ return false;
+ } elseif ($task instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($task, 'horde.error');
+ return false;
+ }
+
+ $result = new stdClass;
+ $result->task = $task->toJson(true, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A');
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function SaveTask($vars)
+ {
+ if (!$GLOBALS['registry']->hasMethod('tasks/updateTask') ||
+ !$GLOBALS['registry']->hasMethod('tasks/addTask')) {
+ return false;
+ }
+
+ $id = $vars->task_id;
+ $list = $vars->old_tasklist;
+ $task = $vars->task;
+
+ $due = trim($task['due_date'] . ' ' . $task['due_time']);
+ if (!empty($due)) {
+ // strptime() is locale dependent, i.e. %p is not always matching
+ // AM/PM. Set the locale to C to workaround this, but grab the
+ // locale's D_FMT before that.
+ $date_format = Horde_Nls::getLangInfo(D_FMT);
+ $old_locale = setlocale(LC_TIME, 0);
+ setlocale(LC_TIME, 'C');
+ $format = $date_format . ' ' . ($GLOBALS['prefs']->getValue('twentyFour') ? '%H:%M' : '%I:%M %p');
+
+ // Try exact format match first.
+ if ($date_arr = strptime($due, $format)) {
+ $task['due'] = new Horde_Date(
+ array('year' => $date_arr['tm_year'] + 1900,
+ 'month' => $date_arr['tm_mon'] + 1,
+ 'mday' => $date_arr['tm_mday'],
+ 'hour' => $date_arr['tm_hour'],
+ 'min' => $date_arr['tm_min'],
+ 'sec' => $date_arr['tm_sec']));
+ } else {
+ $task['due'] = new Horde_Date($due);
+ }
+ setlocale(LC_TIME, $old_locale);
+ }
+
+ $task['alarm'] = $task['alarm']['on']
+ ? $task['alarm']['value'] * $task['alarm']['unit']
+ : 0;
+
+ $result = ($id && $list)
+ ? $GLOBALS['registry']->tasks->updateTask($list, $id, $task)
+ : $GLOBALS['registry']->tasks->addTask($task);
+ if ($result instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($result, 'horde.error');
+ return false;
+ }
+
+ if (!$id) {
+ $id = $result[0];
+ }
+ $task = $GLOBALS['registry']->tasks->getTask($task['tasklist'], $id);
+ if ($task instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($task, 'horde.error');
+ return false;
+ }
+
+ $result = new stdClass;
+ $result->type = $task->completed ? 'complete' : 'incomplete';
+ $result->list = $task->tasklist;
+ $result->sig = $vars->sig;
+ $result->tasks = array($id => $task->toJson(false, $GLOBALS['prefs']->getValue('twentyFour') ? 'H:i' : 'h:i A'));
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function DeleteTask($vars)
+ {
+ if (!$GLOBALS['registry']->hasMethod('tasks/deleteTask') ||
+ !isset($vars->id) ||
+ !isset($vars->list)) {
+ return false;
+ }
+
+ $result = $GLOBALS['registry']->tasks->deleteTask($vars->list, $vars->id);
+ if ($result instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($result, 'horde.error');
+ return false;
+ }
+
+ $result = new stdClass;
+ $result->deleted = true;
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function ToggleCompletion($vars)
+ {
+ if (!$GLOBALS['registry']->hasMethod('tasks/toggleCompletion')) {
+ return false;
+ }
+
+ $saved = $GLOBALS['registry']->call('tasks/toggleCompletion', array($vars->id, $vars->list));
+ if ($saved instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($saved, 'horde.error');
+ return false;
+ }
+
+ $result = new stdClass;
+ $result->toggled = true;
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function ListTopTags($vars)
+ {
+ $tagger = new Kronolith_Tagger();
+ $result = new stdClass;
+ $result->tags = array();
+ $tags = $tagger->getCloud(Horde_Auth::getAuth(), 10);
+ foreach ($tags as $tag) {
+ $result->tags[] = $tag['tag_name'];
+ }
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function GetFreeBusy($vars)
+ {
+ $fb = Kronolith_FreeBusy::get($vars->email, true);
+ if ($fb instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($fb->getMessage(), 'horde.warning');
+ return false;
+ }
+ $result = new stdClass;
+ $result->fb = $fb;
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function SearchCalendars($vars)
+ {
+ $result = new stdClass;
+ $result->events = 'Searched for calendars: ' . $vars->title;
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function SaveCalendar($vars)
+ {
+ $calendar_id = $vars->calendar;
+ $result = new stdClass;
+
+ switch ($vars->type) {
+ case 'internal':
+ $info = array();
+ foreach (array('name', 'color', 'description', 'tags') as $key) {
+ $info[$key] = $vars->$key;
+ }
+
+ // Create a calendar.
+ if (!$calendar_id) {
+ if (!Horde_Auth::getAuth() ||
+ $GLOBALS['prefs']->isLocked('default_share')) {
+ return false;
+ }
+ $calendar = Kronolith::addShare($info);
+ if ($calendar instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($calendar, 'horde.error');
+ return false;
+ }
+ $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been created."), $info['name']), 'horde.success');
+ $result->calendar = $calendar->getName();
+ break;
+ }
+
+ // Update a calendar.
+ $calendar = $GLOBALS['kronolith_shares']->getShare($calendar_id);
+ if ($calendar instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($calendar, 'horde.error');
+ return false;
+ }
+ $original_name = $calendar->get('name');
+ $updated = Kronolith::updateShare($calendar, $info);
+ if ($updated instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($updated, 'horde.error');
+ return false;
+
+ }
+ if ($calendar->get('name') != $original_name) {
+ $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been renamed to \"%s\"."), $original_name, $calendar->get('name')), 'horde.success');
+ } else {
+ $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been saved."), $original_name), 'horde.success');
+ }
+ break;
+
+ case 'tasklists':
+ $calendar = array();
+ foreach (array('name', 'color', 'description') as $key) {
+ $calendar[$key] = $vars->$key;
+ }
+
+ // Create a task list.
+ if (!$calendar_id) {
+ if (!Horde_Auth::getAuth() ||
+ $GLOBALS['prefs']->isLocked('default_share')) {
+ return false;
+ }
+ $tasklist = $GLOBALS['registry']->tasks->addTasklist($calendar['name'], $calendar['description'], $calendar['color']);
+ if ($tasklist instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($tasklist, 'horde.error');
+ return false;
+ }
+ $GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been created."), $calendar['name']), 'horde.success');
+ $result->calendar = $tasklist;
+ break;
+ }
+
+ // Update a task list.
+ $calendar_id = substr($calendar_id, 6);
+ $tasklists = $GLOBALS['registry']->tasks->listTasklists(true, Horde_Perms::EDIT);
+ if (!isset($tasklists[$calendar_id])) {
+ $GLOBALS['notification']->push(_("You are not allowed to change this task list."), 'horde.error');
+ return false;
+ }
+ $updated = $GLOBALS['registry']->tasks->updateTasklist($calendar_id, $calendar);
+ if ($updated instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($updated, 'horde.error');
+ return false;
+ }
+ if ($tasklists[$calendar_id]->get('name') != $calendar['name']) {
+ $GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been renamed to \"%s\"."), $tasklists[$calendar_id]->get('name'), $calendar['name']), 'horde.success');
+ } else {
+ $GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been saved."), $tasklists[$calendar_id]->get('name')), 'horde.success');
+ }
+ break;
+
+ case 'remote':
+ $calendar = array();
+ foreach (array('name', 'description', 'url', 'color', 'username', 'password') as $key) {
+ $calendar[$key] = $vars->$key;
+ }
+ $subscribed = Kronolith::subscribeRemoteCalendar($calendar);
+ if ($subscribed instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($subscribed, 'horde.error');
+ return false;
+ }
+ if ($calendar_id) {
+ $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been saved."), $calendar['name']), 'horde.success');
+ } else {
+ $GLOBALS['notification']->push(sprintf(_("You have been subscribed to \"%s\" (%s)."), $calendar['name'], $calendar['url']), 'horde.success');
+ }
+ break;
+ }
+
+ $result->saved = true;
+ $result->color = Kronolith::foregroundColor($calendar);
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function DeleteCalendar($vars)
+ {
+ $calendar_id = $vars->calendar;
+
+ switch ($vars->type) {
+ case 'internal':
+ $calendar = $GLOBALS['kronolith_shares']->getShare($calendar_id);
+ if ($calendar instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($calendar, 'horde.error');
+ return false;
+ }
+ $deleted = Kronolith::deleteShare($calendar);
+ if ($deleted instanceof PEAR_Error) {
+ $GLOBALS['notification']->push(sprintf(_("Unable to delete \"%s\": %s"), $calendar->get('name'), $deleted->getMessage()), 'horde.error');
+ return false;
+ }
+ $GLOBALS['notification']->push(sprintf(_("The calendar \"%s\" has been deleted."), $calendar->get('name')), 'horde.success');
+ break;
+
+ case 'tasklists':
+ $calendar_id = substr($calendar_id, 6);
+ $tasklists = $GLOBALS['registry']->tasks->listTasklists(true);
+ if (!isset($tasklists[$calendar_id])) {
+ $GLOBALS['notification']->push(_("You are not allowed to delete this task list."), 'horde.error');
+ return false;
+ }
+ $deleted = $GLOBALS['registry']->tasks->deleteTasklist($calendar_id);
+ if ($deleted instanceof PEAR_Error) {
+ $GLOBALS['notification']->push(sprintf(_("Unable to delete \"%s\": %s"), $tasklists[$calendar_id]->get('name'), $deleted->getMessage()), 'horde.error');
+ return false;
+ }
+ $GLOBALS['notification']->push(sprintf(_("The task list \"%s\" has been deleted."), $tasklists[$calendar_id]->get('name')), 'horde.success');
+ break;
+
+ case 'remote':
+ $deleted = Kronolith::unsubscribeRemoteCalendar($calendar_id);
+ if ($deleted instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($deleted, 'horde.error');
+ return false;
+ }
+ $GLOBALS['notification']->push(sprintf(_("You have been unsubscribed from \"%s\" (%s)."), $deleted['name'], $deleted['url']), 'horde.success');
+ break;
+ }
+
+ $result = new stdClass;
+ $result->deleted = true;
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function GetRemoteInfo($vars)
+ {
+ $params = array();
+ if ($user = $vars->username) {
+ $params['user'] = $user;
+ $params['password'] = $vars->password;
+ }
+ if (!empty($GLOBALS['conf']['http']['proxy']['proxy_host'])) {
+ $params['proxy'] = $GLOBALS['conf']['http']['proxy'];
+ }
+ $driver = Kronolith_Driver::factory('Ical', $params);
+ $driver->open($vars->url);
+ try {
+ $ical = $driver->getRemoteCalendar(false);
+ } catch (Kronolith_Exception $e) {
+ if ($e->getCode() == 401) {
+ $result = new stdClass;
+ $result->auth = true;
+ return $result;
+ }
+ throw $e;
+ }
+ $result = new stdClass;
+ $result->success = true;
+ $name = $ical->getAttribute('X-WR-CALNAME');
+ if (!($name instanceof PEAR_Error)) {
+ $result->name = $name;
+ }
+ $desc = $ical->getAttribute('X-WR-CALDESC');
+ if (!($desc instanceof PEAR_Error)) {
+ $result->desc = $desc;
+ }
+
+ return $result;
+ }
+
+ /**
+ * TODO
+ */
+ public function SaveCalPref($vars)
+ {
+ return false;
+ }
+
+ /**
+ * TODO
+ */
+ protected function _getDriver($cal)
+ {
+ list($driver, $calendar) = explode('|', $cal);
+ if ($driver == 'internal' &&
+ !array_key_exists($calendar,
+ Kronolith::listCalendars(false, Horde_Perms::SHOW))) {
+ $GLOBALS['notification']->push(_("Permission Denied"), 'horde.error');
+ return false;
+ }
+ $kronolith_driver = Kronolith::getDriver($driver, $calendar);
+ if ($kronolith_driver instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($kronolith_driver, 'horde.error');
+ return false;
+ }
+ if ($driver == 'remote') {
+ $kronolith_driver->setParam('timeout', 15);
+ }
+ return $kronolith_driver;
+ }
+
+ /**
+ * TODO
+ */
+ protected function _saveEvent($event)
+ {
+ $result = $event->save();
+ if ($result instanceof PEAR_Error) {
+ $GLOBALS['notification']->push($result, 'horde.error');
+ return true;
+ }
+ $start = new Horde_Date(Horde_Util::getFormData('view_start'));
+ $end = new Horde_Date(Horde_Util::getFormData('view_end'));
+ $end->hour = 23;
+ $end->min = $end->sec = 59;
+ Kronolith::addEvents($events, $event, $start, $end, true, true);
+ $result = new stdClass;
+ $result->cal = $event->calendarType . '|' . $event->calendar;
+ $result->view = Horde_Util::getFormData('view');
+ $result->sig = $start->dateString() . $end->dateString();
+ if (count($events)) {
+ $result->events = $events;
+ }
+ return $result;
+ }
+
+}
/* Variables used in core javascript files. */
$code['conf'] = array(
- 'URI_AJAX' => (string)Horde::url($kronolith_webroot . '/ajax.php', true, -1),
+ 'URI_AJAX' => Horde::getServiceLink('ajax', 'kronolith'),
'URI_IMG' => $registry->getImageDir() . '/',
'URI_SNOOZE' => (string)Horde::url($registry->get('webroot', 'horde') . '/services/snooze.php', true, -1),
'SESSION_ID' => defined('SID') ? SID : '',
+++ /dev/null
-<?php
-/**
- * ajax.php defines an set of brower procedure mechanisms
- * for the Shout application.
- *
- * Copyright 2010 Alkaloid Networks LLC (http://projects.alkaloid.net)
- *
- * See the enclosed file COPYING for license information (BSD). If you
- * did not receive this file, see
- * http://www.opensource.org/licenses/bsd-license.php.
- *
- * @author Ben Klang <ben@alkaloid.net>
- * @package Shout
- */
-
-require_once dirname(__FILE__) . '/lib/Application.php';
-
-$action = Horde_Util::getFormData('action');
-if (empty($action)) {
- // This is the only case where we really don't return anything, since
- // the frontend can be presumed not to make this request on purpose.
- // Other missing data cases we return a response of boolean false.
- exit;
-}
-
-try {
- $shout = Horde_Registry::appInit('shout', array('authentication' => 'throw'));
-} catch (Horde_Exception $e) {
- /* Handle session timeouts when they come from an AJAX request. */
- if (($e->getCode() == Horde_Registry::AUTH_FAILURE) &&
- ($action != 'LogOut')) {
- //FIXME: The below is certain to break since it relies on classes I did
- // not yet copy from IMP.
- $notification = &Horde_Notification::singleton();
- $shout_notify = $notification->attach('status', array('viewmode' => 'dimp'), 'Shout_Notification_Listener_Status');
- $notification->push(str_replace('&', '&', Horde_Auth::getLogoutUrl(array('reason' => Horde_Auth::REASON_SESSION))), 'shout.timeout', array('content.raw'));
- Horde::sendHTTPResponse(Horde::prepareResponse(null, $shout_notify), 'json');
- exit;
- }
-
- Horde_Auth::authenticateFailure('shout', $e);
-}
-
-$context = $_SESSION['shout']['context'];
-
-switch($action) {
-case 'addDestination':
- try {
- // FIXME: Use Form?
- $exten = Horde_Util::getFormData('extension');
- $type = Horde_Util::getFormData('type');
- $dest = Horde_Util::getFormData('destination');
- $shout->extensions->addDestination($context, $exten, $type, $dest);
-
- $extensions = $shout->extensions->getExtensions($context);
- Horde::sendHTTPResponse(Horde::prepareResponse($extensions), 'json');
- } catch (Exception $e) {
- Horde::logMessage($e->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
- //FIXME: Create a way to notify the user of the failure.
- }
-
- break;
-
-case 'deleteDestination':
- try {
- // FIXME: Use Form?
- $exten = Horde_Util::getFormData('extension');
- $type = Horde_Util::getFormData('type');
- $dest = Horde_Util::getFormData('destination');
- $shout->extensions->deleteDestination($context, $exten, $type, $dest);
-
- $extensions = $shout->extensions->getExtensions($context);
- Horde::sendHTTPResponse(Horde::prepareResponse($extensions), 'json');
- } catch (Exception $e) {
- Horde::logMessage($e->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
- //FIXME: Create a way to notify the user of the failure.
- }
- break;
-
-case 'getDestinations':
- try {
- $extensions = $shout->extensions->getExtensions($context);
- Horde::sendHTTPResponse(Horde::prepareResponse($extensions), 'json');
- } catch (Exception $e) {
- Horde::logMessage($e->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
- //FIXME: Create a way to notify the user of the failure.
- }
- break;
-}
--- /dev/null
+<?php
+/**
+ * Defines the AJAX interface for Shout.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @author Ben Klang <ben@alkaloid.net>
+ * @package Shout
+ */
+class Shout_Ajax_Application extends Horde_Ajax_Application_Base
+{
+ /**
+ * Returns a notification handler object to use to output any
+ * notification messages triggered by the action.
+ *
+ * @return Horde_Notification_Handler_Base The notification handler.
+ */
+ public function notificationHandler()
+ {
+ return $GLOBALS['kronolith_notify'];
+ }
+
+ /**
+ * TODO
+ */
+ public function addDestination($vars)
+ {
+ $context = $_SESSION['shout']['context'];
+ try {
+ // FIXME: Use Form?
+ $shout = $GLOBALS['registry']->getApiInstance('shout', 'application');
+ $shout->extensions->addDestination($context, $vars->extension, $vars->type, $vars->destination);
+
+ return $shout->extensions->getExtensions($context);
+ } catch (Exception $e) {
+ //FIXME: Create a way to notify the user of the failure.
+ Horde::logMessage($e->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
+ return false;
+ }
+ }
+
+ /**
+ * TODO
+ */
+ public function deleteDestination($vars)
+ {
+ $context = $_SESSION['shout']['context'];
+ try {
+ // FIXME: Use Form?
+ $shout = $GLOBALS['registry']->getApiInstance('shout', 'application');
+ $shout->extensions->deleteDestination($context, $vars->extension, $vars->type, $vars->destination);
+
+ return $shout->extensions->getExtensions($context);
+ } catch (Exception $e) {
+ //FIXME: Create a way to notify the user of the failure.
+ Horde::logMessage($e->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
+ return false;
+ }
+ }
+
+ /**
+ * TODO
+ */
+ public function getDestinations($vars)
+ {
+ $context = $_SESSION['shout']['context'];
+ try {
+ return $shout->extensions->getExtensions($context);
+ } catch (Exception $e) {
+ //FIXME: Create a way to notify the user of the failure.
+ Horde::logMessage($e->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
+ return false;
+ }
+ }
+
+}
+
}
// FIXME: Better error handling
- new Ajax.Request('<?php echo Horde::applicationUrl('ajax.php'); ?>',
+ new Ajax.Request('<?php echo Horde::serviceLink('ajax', 'shout') ?>',
{
method: 'post',
parameters: form.serialize(true),
}
// FIXME: Better error handling
- new Ajax.Request('<?php echo Horde::applicationUrl('ajax.php'); ?>',
+ new Ajax.Request('<?php echo Horde::serviceLink('ajax', 'shout') ?>',
{
method: 'post',
parameters: params,
destinations = $H();
-new Ajax.Request('<?php echo Horde::applicationUrl('ajax.php'); ?>',
+new Ajax.Request('<?php echo Horde::serviceLink('ajax', 'shout') ?>',
{
method: 'post',
parameters: $H({'action': 'getDestinations'}),