}
try {
- $ACLDriver = &IMP_IMAP_ACL::singleton();
+ $ACLDriver = &IMP_Imap_Acl::singleton();
} catch (Horde_Exception $e) {
$notification->push($error, _("This server does not support sharing folders."));
header('Location: ' . $prefs_url);
function _getPollInformation($mbox)
{
- $imptree = IMP_IMAP_Tree::singleton();
+ $imptree = IMP_Imap_Tree::singleton();
$elt = $imptree->get($mbox);
if ($imptree->isPolled($elt)) {
$info = $imptree->getElementInfo($mbox);
break;
}
- $imptree = IMP_IMAP_Tree::singleton();
+ $imptree = IMP_Imap_Tree::singleton();
$imptree->eltDiffStart();
$imp_folder = IMP_Folder::singleton();
break;
}
- $imptree = IMP_IMAP_Tree::singleton();
+ $imptree = IMP_Imap_Tree::singleton();
$imptree->eltDiffStart();
$imp_folder = IMP_Folder::singleton();
break;
}
- $imptree = IMP_IMAP_Tree::singleton();
+ $imptree = IMP_Imap_Tree::singleton();
$imptree->eltDiffStart();
$imp_folder = IMP_Folder::singleton();
break;
case 'ListFolders':
- $imptree = IMP_IMAP_Tree::singleton();
- $result = DIMP::getFolderResponse($imptree, array('a' => $imptree->folderList(IMP_IMAP_TREE::FLIST_CONTAINER | IMP_IMAP_TREE::FLIST_VFOLDER), 'c' => array(), 'd' => array()));
+ $imptree = IMP_Imap_Tree::singleton();
+ $result = DIMP::getFolderResponse($imptree, array('a' => $imptree->folderList(IMP_Imap_Tree::FLIST_CONTAINER | IMP_Imap_Tree::FLIST_VFOLDER), 'c' => array(), 'd' => array()));
$quota = _getQuota();
if (!is_null($quota)) {
case 'PollFolders':
$result = new stdClass;
- $imptree = IMP_IMAP_Tree::singleton();
+ $imptree = IMP_Imap_Tree::singleton();
$result->poll = array();
foreach ($imptree->getPollList(true) as $val) {
$add = Util::getPost('add');
- $imptree = IMP_IMAP_Tree::singleton();
+ $imptree = IMP_Imap_Tree::singleton();
$result = new stdClass;
$result->add = (bool) $add;
/* Use IMP_Tree to determine whether the sent mail folder was
* created. */
- $imptree = &IMP_IMAP_Tree::singleton();
+ $imptree = &IMP_Imap_Tree::singleton();
$imptree->eltDiffStart();
$options = array(
$subscribe = $prefs->getValue('subscribe');
$showAll = (!$subscribe || $_SESSION['imp']['showunsub']);
-/* Initialize the IMP_IMAP_Tree object. */
-$imptree = &IMP_IMAP_Tree::singleton();
-$mask = IMP_IMAP_TREE::NEXT_SHOWCLOSED;
+/* Initialize the IMP_Imap_Tree object. */
+$imptree = &IMP_Imap_Tree::singleton();
+$mask = IMP_Imap_Tree::NEXT_SHOWCLOSED;
/* Toggle subscribed view, if necessary. */
if ($subscribe && Util::getFormData('ts')) {
$showAll = !$showAll;
$_SESSION['imp']['showunsub'] = $showAll;
$imptree->showUnsubscribed($showAll);
- $mask |= IMP_IMAP_TREE::NEXT_SHOWSUB;
+ $mask |= IMP_Imap_Tree::NEXT_SHOWSUB;
}
/* Start iterating through the list of mailboxes, displaying them. */
/* Initialize the IMP_Folder object. */
$imp_folder = &IMP_Folder::singleton();
-/* Initialize the IMP_IMAP_Tree object. */
-$imaptree = &IMP_IMAP_Tree::singleton();
+/* Initialize the IMP_Imap_Tree object. */
+$imaptree = &IMP_Imap_Tree::singleton();
/* $folder_list is already encoded in UTF7-IMAP. */
$charset = NLS::getCharset();
}
/* Get list of mailboxes to poll. */
- $imptree = &IMP_IMAP_Tree::singleton();
+ $imptree = &IMP_Imap_Tree::singleton();
$folders = $imptree->getPollList(true, true);
$anyUnseen = false;
}
/* Get list of mailboxes to poll. */
- $imaptree = &IMP_IMAP_Tree::singleton();
+ $imaptree = &IMP_Imap_Tree::singleton();
$folders = $imaptree->getPollList(true, true);
/* Quota info, if available. */
$name_url = Util::addParameter(Horde::applicationUrl('mailbox.php'), 'no_newmail_popup', 1);
/* Initialize the IMP_Tree object. */
- $imaptree = &IMP_IMAP_Tree::singleton();
- $mask = IMP_IMAP_Tree::NEXT_SHOWCLOSED;
+ $imaptree = &IMP_Imap_Tree::singleton();
+ $mask = IMP_Imap_Tree::NEXT_SHOWCLOSED;
if ($GLOBALS['prefs']->getValue('subscribe')) {
- $mask |= IMP_IMAP_Tree::NEXT_SHOWSUB;
+ $mask |= IMP_Imap_Tree::NEXT_SHOWSUB;
}
$unseen = 0;
class DIMP
{
/**
+ * Charset cache.
+ */
+ static protected $_charset;
+
+ /**
* Output a dimp-style action (menubar) link.
*
* @param array $params A list of parameters.
*
* @return string An HTML link to $url.
*/
- public function actionButton($params = array())
+ static public function actionButton($params = array())
{
$tooltip = (empty($params['tooltip'])) ? '' : $params['tooltip'];
if (empty($params['title'])) {
- static $charset;
- if (!isset($charset)) {
- $charset = NLS::getCharset();
+ if (!isset(self::$_charset)) {
+ self::$_charset = NLS::getCharset();
}
$old_error = error_reporting(0);
- $tooltip = nl2br(htmlspecialchars($tooltip, ENT_QUOTES, $charset));
+ $tooltip = nl2br(htmlspecialchars($tooltip, ENT_QUOTES, self::$_charset));
$title = $ak = '';
} else {
$title = $params['title'];
* Each entry contains the three elements necessary
* for a Horde::addScriptFile() call.
*/
- public function header($title, $scripts = array())
+ static public function header($title, $scripts = array())
{
// Don't autoload any javascript files.
Horde::disableAutoloadHordeJS();
*
* @return string TODO
*/
- protected function _includeDIMPJSVars()
+ static protected function _includeDIMPJSVars()
{
global $browser, $conf, $prefs, $registry;
/**
* Return an appended IMP folder string
*/
- private function _appendedFolderPref($folder)
+ static private function _appendedFolderPref($folder)
{
return IMP::folderPref($folder, true);
}
*
* @return string The notification JS code.
*/
- public function notify()
+ static public function notify()
{
$GLOBALS['notification']->notify(array('listeners' => 'status'));
$msgs = $GLOBALS['imp_notify']->getStack(true);
*
* @return array The object used by the JS code to update the folder tree.
*/
- public function getFolderResponse($imptree, $changes = null)
+ static public function getFolderResponse($imptree, $changes = null)
{
- if ($changes === null) {
+ if (is_null($changes)) {
$changes = $imptree->eltDiff();
}
if (empty($changes)) {
foreach ($changes['c'] as $val) {
// Skip the base element, since any change there won't ever be
// updated on-screen.
- if ($val != IMP_IMAP_TREE::BASE_ELT) {
+ if ($val != IMP_Imap_Tree::BASE_ELT) {
$result['c'][] = DIMP::_createFolderElt($imptree->element($val));
}
}
* 'v' (virtual) = Is this a virtual folder? [boolean] [DEFAULT: no]
* </pre>
*/
- private function _createFolderElt($elt)
+ static private function _createFolderElt($elt)
{
$ob = new stdClass;
if ($elt['children']) {
}
switch ($elt['special']) {
- case IMP_IMAP_TREE::SPECIAL_INBOX:
+ case IMP_Imap_Tree::SPECIAL_INBOX:
$ob->cl = 'inbox';
$ob->s = 1;
break;
- case IMP_IMAP_TREE::SPECIAL_TRASH:
+ case IMP_Imap_Tree::SPECIAL_TRASH:
$ob->cl = 'trash';
$ob->s = 1;
break;
- case IMP_IMAP_TREE::SPECIAL_SPAM:
+ case IMP_Imap_Tree::SPECIAL_SPAM:
$ob->cl = 'spam';
$ob->s = 1;
break;
- case IMP_IMAP_TREE::SPECIAL_DRAFT:
+ case IMP_Imap_Tree::SPECIAL_DRAFT:
$ob->cl = 'drafts';
$ob->s = 1;
break;
- case IMP_IMAP_TREE::SPECIAL_SENT:
+ case IMP_Imap_Tree::SPECIAL_SENT:
$ob->cl = 'sent';
$ob->s = 1;
break;
* 'size' - The size of the attachment in KB (string)
* </pre>
*/
- public function getAttachmentInfo($imp_compose)
+ static public function getAttachmentInfo($imp_compose)
{
$fwd_list = array();
*
* @return array The array of menu items.
*/
- public function menuList()
+ static public function menuList()
{
if (isset($GLOBALS['conf']['dimp']['menu']['apps'])) {
$apps = $GLOBALS['conf']['dimp']['menu']['apps'];
*
* @return string The link to the message composition screen.
*/
- public function composeLink($args = array(), $extra = array())
+ static public function composeLink($args = array(), $extra = array())
{
// IE 6 & 7 handles window.open() URL param strings differently if
// triggered via an href or an onclick. Since we have no hint
return $this->_listCache[$sig];
}
- $imaptree = IMP_IMAP_Tree::singleton();
+ $imaptree = IMP_Imap_Tree::singleton();
- $list_mask = IMP_IMAP_Tree::FLIST_CONTAINER | IMP_IMAP_Tree::FLIST_OB;
+ $list_mask = IMP_Imap_Tree::FLIST_CONTAINER | IMP_Imap_Tree::FLIST_OB;
if (!$sub) {
- $list_mask |= IMP_IMAP_Tree::FLIST_UNSUB;
+ $list_mask |= IMP_Imap_Tree::FLIST_UNSUB;
}
$flist = $imaptree->folderList($list_mask);
if (!empty($deleted)) {
/* Update the IMAP_Tree cache. */
- $imaptree = IMP_IMAP_Tree::singleton();
+ $imaptree = IMP_Imap_Tree::singleton();
$imaptree->delete($deleted);
$this->_onDelete($deleted);
$this->clearFlistCache();
/* Update the IMAP_Tree object. */
- $imaptree = IMP_IMAP_Tree::singleton();
+ $imaptree = IMP_Imap_Tree::singleton();
$imaptree->insert($folder);
/* Recreate Virtual Folders. */
*/
public function exists($folder)
{
- $imaptree = IMP_IMAP_Tree::singleton();
+ $imaptree = IMP_Imap_Tree::singleton();
$elt = $imaptree->get($folder);
if ($elt) {
return !$imaptree->isContainer($elt);
$deleted = array($old);
$inserted = array($new);
- $imaptree = IMP_IMAP_Tree::singleton();
+ $imaptree = IMP_Imap_Tree::singleton();
/* Get list of any folders that are underneath this one. */
- $all_folders = array_merge(array($old), $imaptree->folderList(IMP_IMAP_Tree::FLIST_UNSUB, $old));
+ $all_folders = array_merge(array($old), $imaptree->folderList(IMP_Imap_Tree::FLIST_UNSUB, $old));
$sub_folders = $imaptree->folderList();
try {
if (!empty($subscribed)) {
/* Initialize the IMAP_Tree object. */
- $imaptree = IMP_IMAP_Tree::singleton();
+ $imaptree = IMP_Imap_Tree::singleton();
$imaptree->subscribe($subscribed);
/* Reset the folder cache. */
if (!empty($unsubscribed)) {
/* Initialize the IMAP_Tree object. */
- $imaptree = IMP_IMAP_Tree::singleton();
+ $imaptree = IMP_Imap_Tree::singleton();
$imaptree->unsubscribe($unsubscribed);
/* Reset the folder cache. */
+++ /dev/null
-<?php
-/**
- * The IMP_IMAP:: class provides common functions for interaction with the
- * IMAP/POP3 server via the Horde_Imap_Client:: library.
- *
- * Copyright 2008-2009 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_IMAP
-{
- /**
- * The Horde_Imap_Client object.
- *
- * @var Horde_Imap_Client
- */
- public $ob = null;
-
- /**
- * The Horde_Imap_Client_Utils object.
- *
- * @var Horde_Imap_Client_Utils
- */
- public $utils = null;
-
- /**
- * Is connection read-only?
- *
- * @var array
- */
- protected $_readonly = array();
-
- /**
- * Namespace cache.
- *
- * @var array
- */
- protected $_nscache = array();
-
- /**
- * Default namespace.
- *
- * @var array
- */
- protected $_nsdefault;
-
- /**
- * Constructor.
- */
- function __construct()
- {
- /* Register the logging callback. */
- Horde_Imap_Client_Exception::$logCallback = array($this, 'logException');
-
- /* Rebuild the Horde_Imap_Client object. */
- $this->_loadImapObject();
-
- $this->utils = new Horde_Imap_Client_Utils();
- }
-
- /**
- * Save the Horde_Imap_Client object on session shutdown.
- */
- function __destruct()
- {
- /* Only need to serialize object once a second. When we do serialize,
- * make sure we login in order to ensure we have done the necessary
- * initialization. */
- if ($this->ob &&
- isset($_SESSION['imp']) &&
- !isset($_SESSION['imp']['imap_ob'])) {
- $this->ob->login();
- $_SESSION['imp']['imap_ob'] = serialize($this->ob);
- }
- }
-
- /**
- * Loads the server configuration from servers.php.
- *
- * @param string $server Returns this labeled entry only.
- *
- * @return mixed If $server is set, then return this entry, or return the
- * entire servers array. Returns false on error.
- */
- static public function loadServerConfig($server = null)
- {
- $servers = Horde::loadConfiguration('servers.php', 'servers', 'imp');
- if (is_a($servers, 'PEAR_Error')) {
- Horde::logMessage($servers, __FILE__, __LINE__, PEAR_LOG_ERR);
- return false;
- }
-
- if (is_null($server)) {
- return $servers;
- }
-
- /* Check for the existence of the server in the config file. */
- if (empty($servers[$server]) || !is_array($servers[$server])) {
- $entry = sprintf('Invalid server key "%s" from client [%s]', $server, $_SERVER['REMOTE_ADDR']);
- Horde::logMessage($entry, __FILE__, __LINE__, PEAR_LOG_ERR);
- return false;
- }
-
- return $servers[$server];
- }
-
- /**
- * Loads the Horde_Imap_Client object from serialized session data and
- * loads the object into the global $imp_imap variable.
- *
- * @return boolean True on success, false on error.
- */
- protected function _loadImapObject()
- {
- if (!is_null($this->ob)) {
- return true;
- }
-
- if (!isset($_SESSION['imp']['imap_ob'])) {
- return false;
- }
-
- Horde_Imap_Client::$encryptKey = IMP::getAuthKey();
-
- $old_error = error_reporting(0);
- $this->ob = unserialize($_SESSION['imp']['imap_ob']);
- error_reporting($old_error);
-
- if (empty($this->ob)) {
- // @todo How to handle bad unserialize?
- // @todo Log message
- return false;
- }
-
- $this->_postcreate($_SESSION['imp']['protocol']);
-
- return true;
- }
-
- /**
- * Create a new Horde_Imap_Client object.
- *
- * @param string $username The username to authenticate with.
- * @param string $password The password to authenticate with.
- * @param string $key Create a new object using this server key.
- * @param boolean $global If true, treate the created object as the IMP
- * global IMAP object.
- *
- * @return boolean The object on success, false on error.
- */
- public function createImapObject($username, $password, $key,
- $global = true)
- {
- if ($global && !is_null($this->ob)) {
- return $GLOBALS['imp_imap'];
- }
-
- if (($server = $this->loadServerConfig($key)) === false) {
- return false;
- }
-
- $protocol = isset($server['protocol']) ? strtolower($server['protocol']) : 'imap';
-
- $imap_config = array(
- 'debug' => isset($server['debug']) ? $server['debug'] : null,
- 'hostspec' => isset($server['hostspec']) ? $server['hostspec'] : null,
- 'password' => $password,
- 'port' => isset($server['port']) ? $server['port'] : null,
- 'secure' => isset($server['secure']) ? $server['secure'] : false,
- 'statuscache' => true,
- 'timeout' => !empty($server['timeout']) ? $server['timeout'] : 10,
- 'username' => $username,
- );
-
- /* Initialize caching. */
- if (!empty($server['cache'])) {
- $c = $server['cache'];
- $driver = $GLOBALS['conf']['cache']['driver'];
- if ($driver != 'none') {
- $imap_config['cache'] = array(
- 'comparator' => empty($c['comparator']) ? false : $c['comparator'],
- 'compress' => empty($c['compress']) ? false : $c['compress'],
- 'driver' => $driver,
- 'driver_params' => Horde::getDriverConfig('cache', $driver),
- 'id' => empty($c['id']) ? false : $c['id'],
- 'lang' => empty($c['lang']) ? false : $c['lang'],
- 'lifetime' => empty($c['lifetime']) ? false : $c['lifetime'],
- 'slicesize' => empty($c['slicesize']) ? false : $c['slicesize'],
- );
- }
- }
-
- try {
- $ob = Horde_Imap_Client::getInstance(($protocol == 'imap') ? 'Socket' : 'Cclient_pop3', $imap_config);
- } catch (Horde_Imap_Client_Exception $e) {
- return false;
- }
-
- if ($global) {
- $this->ob = $ob;
- $this->_postcreate($protocol);
- }
-
- return $ob;
- }
-
- /**
- * Alter some IMP settings once we load/create the global object.
- *
- * @param string $protocol The protocol used to connect.
- */
- protected function _postcreate($protocol)
- {
- global $conf, $prefs;
-
- switch ($protocol) {
- case 'pop':
- /* Turn some options off if we are working with POP3. */
- $conf['user']['allow_folders'] = false;
- $prefs->setValue('save_sent_mail', false);
- $prefs->setLocked('save_sent_mail', true);
- $prefs->setLocked('sent_mail_folder', true);
- $prefs->setLocked('drafts_folder', true);
- $prefs->setLocked('trash_folder', true);
- break;
- }
- }
-
- /**
- * Is the current IMAP connection read-only?
- *
- * @param string $mailbox The mailbox.
- *
- * @return boolean Is the connection read-only?
- */
- public function isReadOnly($mailbox)
- {
- if (!isset($this->_readonly[$mailbox])) {
- $this->_readonly[$mailbox] =
- !empty($GLOBALS['conf']['hooks']['mbox_readonly']) &&
- Horde::callHook('_imp_hook_mbox_readonly', array($mailbox), 'imp');
- }
-
- return $this->_readonly[$mailbox];
- }
-
- /**
- * Logs an exception from Horde_Imap_Client.
- *
- * @param object Horde_Imap_Client_Exception $e The exception object.
- */
- public function logException($e)
- {
- Horde::logMessage($e, $e->getFile(), $e->getLine(), PEAR_LOG_ERR);
- }
-
- /**
- * Get the namespace list.
- *
- * @return array An array of namespace information.
- */
- public function getNamespaceList()
- {
- try {
- return $GLOBALS['imp_imap']->ob->getNamespaces(!empty($_SESSION['imp']['imap_ext']['namespace']) ? $_SESSION['imp']['imap_ext']['namespace'] : array());
- } catch (Horde_Imap_Client_Exception $e) {
- // @todo Error handling
- return array();
- }
- }
-
- /**
- * Get namespace info for a full folder path.
- *
- * @param string $mailbox The folder path. If empty, will return info
- * on the default namespace (i.e. the first
- * personal namespace).
- * @param boolean $empty If true and no matching namespace is found,
- * return the empty namespace, if it exists.
- *
- * @return mixed The namespace info for the folder path or null if the
- * path doesn't exist.
- */
- public function getNamespace($mailbox = null, $empty = true)
- {
- if ($_SESSION['imp']['protocol'] == 'pop') {
- return null;
- }
-
- $ns = $this->getNamespaceList();
-
- if ($mailbox === null) {
- reset($ns);
- $mailbox = key($ns);
- }
-
- $key = (int)$empty;
- if (isset($this->_nscache[$key][$mailbox])) {
- return $this->_nscache[$key][$mailbox];
- }
-
- foreach ($ns as $key => $val) {
- $mbx = $mailbox . $val['delimiter'];
- if (!empty($key) && (strpos($mbx, $key) === 0)) {
- $this->_nscache[$key][$mailbox] = $val;
- return $val;
- }
- }
-
- $this->_nscache[$key][$mailbox] = ($empty && isset($ns[''])) ? $ns[''] : null;
-
- return $this->_nscache[$key][$mailbox];
- }
-
- /**
- * Get the default personal namespace.
- *
- * @return mixed The default personal namespace info.
- */
- public function defaultNamespace()
- {
- if ($_SESSION['imp']['protocol'] == 'pop') {
- return null;
- }
-
- if (!isset($this->_nsdefault)) {
- $this->_nsdefault = null;
- foreach ($this->getNamespaceList() as $val) {
- if ($val['type'] == 'personal') {
- $this->_nsdefault = $val;
- break;
- }
- }
- }
-
- return $this->_nsdefault;
- }
-}
+++ /dev/null
-<?php
-/**
- * Contains functions related to managing IMAP Access Control Lists.
- *
- * Copyright 2003-2009 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 Chris Hastie <imp@oak-wood.co.uk>
- * @package IMP
- */
-class IMP_IMAP_ACL
-{
- /**
- * Singleton instance.
- *
- * @var IMP_IMAP_ACL
- */
- static protected $_instance = null;
-
- /**
- * Hash containing the list of possible rights and a human readable
- * description of each.
- *
- * @var array
- */
- protected $_rightsList;
-
- /**
- * Array containing user names that cannot have their access rights
- * changed.
- *
- * @var boolean
- */
- protected $_protected;
-
- /**
- * Attempts to return a reference to a concrete object instance.
- * It will only create a new instance if no instance currently exists.
- *
- * @return IMP_IMAP_ACL The created concrete instance.
- */
- static public function singleton()
- {
- if (!self::$_instance) {
- self::$_instance = new IMP_IMAP_ACL();
- }
-
- return self::$_instance;
- }
-
- /**
- * Constructor.
- */
- protected function __construct()
- {
- if ($_SESSION['imp']['protocol'] != 'imap') {
- throw new Horde_Exception(_("ACL requires an IMAP server."));
- }
-
- $capability = $GLOBALS['imp_imap']->ob->queryCapability('ACL');
- if (!$capability) {
- throw new Horde_Exception(_("IMAP server does not support ACLs."));
- }
-
- $rfc4314 = $GLOBALS['imp_imap']->ob->queryCapability('RIGHTS');
-
- $this->_protected = array($GLOBALS['imp_imap']->ob->getParam('username'));
-
- $this->_rightsList = array(
- 'l' => array(
- 'desc' => _("List - user can see the folder"),
- 'title' => _("List")
- ),
- 'r' => array(
- 'desc' => _("Read messages"),
- 'title' => _("Read")
- ),
- 's' => array(
- 'desc' => _("Mark with Seen/Unseen flags"),
- 'title' => _("Mark (Seen)")
- ),
- 'w' => array(
- 'desc' => _("Mark with other flags (e.g. Important/Answered)"),
- 'title' => _("Mark (Other)")
- ),
- 'i' => array(
- 'desc' => _("Insert messages"),
- 'title' => _("Insert")
- ),
- 'p' => array(
- 'desc' => _("Post to this folder (not enforced by IMAP)"),
- 'title' => _("Post")
- ),
- 'a' => array(
- 'desc' => _("Administer - set permissions for other users"),
- 'title' => _("Administer")
- )
- );
-
- if ($rfc4314) {
- // RFC 4314 compliant rights
- $this->_rightsList = array_merge($this->_rightsList, array(
- 'k' => array(
- 'desc' => _("Create sub folders"),
- 'title' => _("Create Folders")
- ),
- 'x' => array(
- 'desc' => _("Delete sub folders"),
- 'title' => _("Delete Folders")
- ),
- 't' => array(
- 'desc' => _("Delete messages"),
- 'title' => _("Delete")
- ),
- 'e' => array(
- 'desc' => _("Purge messages"),
- 'title' => _("Purge")
- )
- ));
- } else {
- // RFC 2086 compliant rights
- $this->_rightsList = array_merge($this->_rightsList, array(
- 'c' => array(
- 'desc' =>_("Create sub folders"),
- 'title' => _("Create Folder")
- ),
- 'd' => array(
- 'desc' => _("Delete and purge messages"),
- 'title' => _("Delete/Purge")
- )
- ));
- }
- }
-
- /**
- * Attempts to retrieve the existing ACL for a mailbox from the server.
- *
- * @param string $mbox The mailbox to get the ACL for.
- *
- * @return array A hash containing information on the ACL.
- * @throws Horde_Exception
- */
- public function getACL($mbox)
- {
- try {
- return $GLOBALS['imp_imap']->ob->getACL($mbox);
- } catch (Horde_Imap_Client_Exception $e) {
- throw new Horde_Exception(_("Could not retrieve ACL"));
- }
- }
-
- /**
- * Edits an ACL on the server.
- *
- * @param string $mbox The mailbox on which to edit the ACL.
- * @param string $user The user to grant rights to.
- * @param array $acl The keys of which are the rights to be granted
- * (see RFC 2086).
- *
- * @throws Horde_Exception
- */
- public function editACL($mbox, $user, $acl)
- {
- try {
- $GLOBALS['imp_imap']->ob->setACL($mbox, $user, array('rights' => $acl));
- } catch (Horde_Imap_Client_Exception $e) {
- throw new Horde_Exception(sprintf(_("Couldn't give user \"%s\" the following rights for the folder \"%s\": %s"), $user, $mbox, implode('', $acl)));
- }
- }
-
- /**
- * Can a user edit the ACL for this mailbox?
- *
- * @param string $mbox The mailbox name.
- * @param string $user A user name.
- *
- * @return boolean True if $user has 'a' right
- */
- public function canEdit($mbox, $user)
- {
- try {
- $rights = $GLOBALS['imp_imap']->ob->listACLRights($mbox, $user);
- foreach ($rights as $val) {
- if (strpos($val, 'a') !== false) {
- return true;
- }
- }
- return false;
- } catch (Horde_Imap_Client_Exception $e) {
- return false;
- }
- }
-
- /**
- * TODO
- */
- public function getRights()
- {
- return $this->_rightsList;
- }
-
- /**
- * TODO
- */
- public function getProtected()
- {
- return $this->_protected;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * The IMP_IMAP_Thread class provides functions to generate thread tree
- * images.
- *
- * Copyright 2005-2009 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_IMAP_Thread
-{
- /**
- * The thread data object.
- *
- * @var Horde_Imap_Client_Thread
- */
- protected $_thread;
-
- /**
- * Images used and their internal representations.
- *
- * @var array
- */
- static protected $_imglist = array(
- '0' => 'blank.png',
- '1' => 'line.png',
- '2' => 'join.png',
- '3' => 'joinbottom-down.png',
- '4' => 'joinbottom.png'
- );
-
- /**
- * Constructor.
- *
- * @param Horde_Imap_Client_Thread $thread The thread data object.
- */
- function __construct($thread)
- {
- $this->_thread = $thread;
- }
-
- /**
- * Generate the thread representation for the given index list in the
- * internal format (a string with each character representing the graphic
- * to be displayed from $_imglist).
- *
- * @param array $indices The list of indices to create a tree for.
- * @param boolean $sortdir True for newest first, false for oldest first.
- *
- * @return array An array with the index as the key and the internal
- * thread representation as the value.
- */
- public function getThreadTreeOb($indices, $sortdir)
- {
- $container = $last_level = $last_thread = null;
- $thread_level = $tree = array();
- $t = &$this->_thread;
-
- $indices = array_intersect($t->messageList($sortdir), $indices);
-
- /* If starting in the middle of a thread, the threadLevel tree needs
- * to be built from the base of the current thread. */
- $first = reset($indices);
- foreach ($t->getThread(reset($indices)) as $val) {
- if ($first == $val) {
- break;
- }
- $thread_level[$t->getThreadIndent($val)] = $t->lastInLevel($val);
- }
-
- foreach ($indices as $val) {
- $tree[$val] = '';
-
- $indentBase = $t->getThreadBase($val);
- if (empty($indentBase)) {
- continue;
- }
-
- $lines = '';
- $indentLevel = $t->getThreadIndent($val);
- $lastinlevel = $t->lastInLevel($val);
-
- if ($lastinlevel && ($indentBase == $val)) {
- continue;
- }
-
- if ($lastinlevel) {
- $join_img = ($sortdir) ? 3 : 4;
- } elseif (($indentLevel == 1) && ($indentBase == $val)) {
- $join_img = ($sortdir) ? 4 : 3;
- } else {
- $join_img = 2;
- }
-
- $thread_level[$indentLevel] = $lastinlevel;
- $line = '';
-
- for ($i = 1; $i < $indentLevel; ++$i) {
- $line .= (!isset($thread_level[$i]) || ($thread_level[$i])) ? 0 : 1;
- }
- $tree[$val] = $line . $join_img;
- }
-
- return $tree;
- }
-
- /**
- * Generate the thread representation image for the given index list.
- *
- * @param array $indices The list of indices to create a tree for.
- * @param boolean $sortdir True for newest first, false for oldest first.
- *
- * @return array An array with the index as the key and the thread image
- * representation as the value.
- */
- public function getThreadImageTree($indices, $sortdir)
- {
- $imgs = $tree = array();
-
- foreach (self::$_imglist as $key => $val) {
- $imgs[$key] = Horde::img('tree/' . (($key != 0 && !empty($GLOBALS['nls']['rtl'][$GLOBALS['language']])) ? ('rev-' . $val) : $val), null, null, $GLOBALS['registry']->getImageDir('horde'));
- }
-
- foreach ($this->getThreadTreeOb($indices, $sortdir) as $k => $v) {
- $tree[$k] = '';
- for ($i = 0, $length = strlen($v); $i < $length; ++$i) {
- $tree[$k] .= $imgs[$v[$i]];
- }
- }
- return $tree;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * The IMP_IMAP_Tree class provides a tree view of the mailboxes in an
- * IMAP/POP3 repository. It provides access functions to iterate through this
- * tree and query information about individual mailboxes.
- * In IMP, folders = IMAP mailboxes so the two terms are used interchangably.
- *
- * Copyright 2000-2009 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 Chuck Hagenbuch <chuck@horde.org>
- * @author Jon Parise <jon@horde.org>
- * @author Anil Madhavapeddy <avsm@horde.org>
- * @author Michael Slusarz <slusarz@horde.org>
- * @package IMP
- */
-class IMP_IMAP_Tree
-{
- /* Constants for mailboxElt attributes. */
- const ELT_NOSELECT = 1;
- const ELT_NAMESPACE = 2;
- const ELT_IS_OPEN = 4;
- const ELT_IS_SUBSCRIBED = 8;
- const ELT_NOSHOW = 16;
- const ELT_IS_POLLED = 32;
- const ELT_NEED_SORT = 64;
- const ELT_VFOLDER = 128;
- const ELT_NONIMAP = 256;
- const ELT_INVISIBLE = 512;
-
- /* The isOpen() expanded mode constants. */
- const OPEN_NONE = 0;
- const OPEN_ALL = 1;
- const OPEN_USER = 2;
-
- /* The manner to which to traverse the tree when calling next(). */
- const NEXT_SHOWCLOSED = 1;
- const NEXT_SHOWSUB = 2;
-
- /* The string used to indicate the base of the tree. */
- const BASE_ELT = '%';
-
- /* Defines used with the output from the build() function. */
- const SPECIAL_INBOX = 1;
- const SPECIAL_TRASH = 2;
- const SPECIAL_DRAFT = 3;
- const SPECIAL_SPAM = 4;
- const SPECIAL_SENT = 5;
-
- /* Defines used with folderList(). */
- const FLIST_CONTAINER = 1;
- const FLIST_UNSUB = 2;
- const FLIST_OB = 4;
- const FLIST_VFOLDER = 8;
-
- /* Add a percent to folder key since it allows us to sort by name but
- * never conflict with an IMAP mailbox of the same name (since '%' is an
- * invalid character in an IMAP mailbox string). */
- public $VFOLDER_LABEL;
- public $VFOLDER_KEY;
-
- /* Defines used with namespace display. */
- public $SHARED_LABEL;
- public $SHARED_KEY;
- public $OTHER_LABEL;
- public $OTHER_KEY;
-
- /**
- * Array containing the mailbox tree.
- *
- * @var array
- */
- protected $_tree;
-
- /**
- * Location of current element in the tree.
- *
- * @var string
- */
- protected $_currparent = null;
-
- /**
- * Location of current element in the tree.
- *
- * @var integer
- */
- protected $_currkey = null;
-
- /**
- * Location of current element in the tree.
- *
- * @var array
- */
- protected $_currstack = array();
-
- /**
- * Show unsubscribed mailboxes?
- *
- * @var boolean
- */
- protected $_showunsub = false;
-
- /**
- * Parent list.
- *
- * @var array
- */
- protected $_parent = array();
-
- /**
- * The cached list of mailboxes to poll.
- *
- * @var array
- */
- protected $_poll = null;
-
- /**
- * The cached list of expanded folders.
- *
- * @var array
- */
- protected $_expanded = null;
-
- /**
- * Cached list of subscribed mailboxes.
- *
- * @var array
- */
- protected $_subscribed = null;
-
- /**
- * The cached full list of mailboxes on the server.
- *
- * @var array
- */
- protected $_fulllist = null;
-
- /**
- * Tree changed flag. Set when something in the tree has been altered.
- *
- * @var boolean
- */
- protected $_changed = false;
-
- /**
- * Have we shown unsubscribed folders previously?
- *
- * @var boolean
- */
- protected $_unsubview = false;
-
- /**
- * The string used for the IMAP delimiter.
- *
- * @var string
- */
- protected $_delimiter = '/';
-
- /**
- * The list of namespaces to add to the tree.
- *
- * @var array
- */
- protected $_namespaces = array();
-
- /**
- * Used to determine the list of element changes.
- *
- * @var array
- */
- protected $_eltdiff = null;
-
- /**
- * If set, track element changes.
- *
- * @var boolean
- */
- protected $_trackdiff = true;
-
- /**
- * See $open parameter in build().
- *
- * @var boolean
- */
- protected $_forceopen = false;
-
- /**
- * Attempts to return a reference to a concrete IMP_IMAP_Tree instance.
- *
- * If an IMP_IMAP_Tree object is currently stored in the cache, re-create
- * that object. Else, create a new instance. Ensures that only one
- * instance is available at any time.
- *
- * @return IMP_IMAP_Tree The object or null.
- */
- static public function singleton()
- {
- static $instance;
-
- if (!isset($instance)) {
- if (!empty($_SESSION['imp']['cache']['tree'])) {
- $imp_cache = IMP::getCache();
- $instance = unserialize($imp_cache->get($_SESSION['imp']['cache']['tree'], 86400));
- }
- if (empty($instance)) {
- $instance = new IMP_IMAP_Tree();
- }
- }
-
- return $instance;
- }
-
- /**
- * Constructor.
- */
- protected function __construct()
- {
- if ($_SESSION['imp']['protocol'] == 'imap') {
- $ns = $GLOBALS['imp_imap']->getNamespaceList();
- $ptr = reset($ns);
- $this->_delimiter = $ptr['delimiter'];
- $this->_namespaces = (empty($GLOBALS['conf']['user']['allow_folders'])) ? array() : $ns;
- }
-
- if (!isset($_SESSION['imp']['cache']['tree'])) {
- $imp_cache = IMP::getCache();
- $_SESSION['imp']['cache']['tree'] = $imp_cache
- ? uniqid(mt_rand() . Auth::getAuth())
- : null;
- }
-
- /* Must set these values here because PHP 5 does not allow assignment
- * of const's to gettext strings. */
- $this->VFOLDER_LABEL = _("Virtual Folders");
- $this->VFOLDER_KEY = $this->VFOLDER_LABEL . '%';
- $this->SHARED_LABEL = _("Shared Folders");
- $this->SHARED_KEY = $this->SHARED_LABEL . '%';
- $this->OTHER_LABEL = _("Other Users' Folders");
- $this->OTHER_KEY = $this->OTHER_LABEL . '%';
-
- $this->init();
- }
-
- /**
- * Do cleanup prior to serialization and provide a list of variables
- * to serialize.
- */
- function __sleep()
- {
- /* Don't store $_expanded and $_poll - these values are handled
- * by the subclasses.
- * Don't store $_eltdiff - these needs to be regenerated for each
- * request.
- * Don't store $_currkey, $_currparent, and $_currstack since the
- * user MUST call reset() before cycling through the tree.
- * Don't store $_subscribed and $_fulllist - this information is
- * stored in the elements.
- * Reset the $_changed and $_trackdiff flags. */
- $this->_currkey = $this->_currparent = $this->_eltdiff = $this->_expanded = $this->_fulllist = $this->_poll = $this->_subscribed = null;
- $this->_currstack = array();
- $this->_changed = false;
- $this->_trackdiff = true;
-
- return array_keys(get_class_vars(__CLASS__));
- }
-
- /**
- * Store a serialized version of ourself in the current session.
- */
- function __destruct()
- {
- /* We only need to store the object if using Horde_Cache and the tree
- * has changed. */
- if (empty($this->_changed) ||
- is_null($_SESSION['imp']['cache']['tree'])) {
- return;
- }
-
- $imp_cache = IMP::getCache();
- $imp_cache->set($_SESSION['imp']['cache']['tree'], serialize($this), 86400);
- }
-
- /**
- * Returns the list of mailboxes on the server.
- *
- * @param boolean $showunsub Show unsubscribed mailboxes?
- *
- * @return array A list of mailbox names.
- */
- protected function _getList($showunsub)
- {
- if ($showunsub && !is_null($this->_fulllist)) {
- return $this->_fulllist;
- } elseif (!$showunsub && !is_null($this->_subscribed)) {
- return array_keys($this->_subscribed);
- }
-
- /* INBOX must always appear. */
- $names = array('INBOX');
-
- foreach ($this->_namespaces as $key => $val) {
- try {
- $names = array_merge($names, $GLOBALS['imp_imap']->ob->listMailboxes($key . '*', $showunsub ? Horde_Imap_Client::MBOX_ALL : Horde_Imap_Client::MBOX_SUBSCRIBED, array('flat' => true)));
- if ($showunsub) {
- $this->_fulllist = $names;
- } else {
- $this->_subscribed = $names;
- }
- } catch (Horde_Imap_Client_Exception $e) {}
- }
-
- return $names;
- }
-
- /**
- * Make a single mailbox tree element.
- * An element consists of the following items (we use single letters here
- * to save in session storage space):
- * 'a' -- Attributes
- * 'c' -- Level count
- * 'l' -- Label
- * 'p' -- Parent node
- * 'v' -- Value
- *
- * @param string $name The mailbox name.
- * @param integer $attributes The mailbox's attributes.
- *
- * @return array See above format.
- */
- protected function _makeElt($name, $attributes = 0)
- {
- $elt = array(
- 'a' => $attributes,
- 'c' => 0,
- 'p' => self::BASE_ELT,
- 'v' => $name
- );
-
- /* Set subscribed values. We know the folder is subscribed, without
- * query of the IMAP server, in the following situations:
- * + Folder is INBOX.
- * + We are adding while in subscribe-only mode.
- * + Subscriptions are turned off. */
- if (!$this->isSubscribed($elt)) {
- if (!$this->_showunsub ||
- ($elt['v'] == 'INBOX') ||
- !$GLOBALS['prefs']->getValue('subscribe')) {
- $this->_setSubscribed($elt, true);
- } else {
- $this->_initSubscribed();
- $this->_setSubscribed($elt, isset($this->_subscribed[$elt['v']]));
- }
- }
-
- /* Check for polled status. */
- $this->_initPollList();
- $this->_setPolled($elt, isset($this->_poll[$elt['v']]));
-
- /* Check for open status. */
- switch ($GLOBALS['prefs']->getValue('nav_expanded')) {
- case self::OPEN_NONE:
- $open = false;
- break;
-
- case self::OPEN_ALL:
- $open = true;
- break;
-
- case self::OPEN_USER:
- $this->_initExpandedList();
- $open = !empty($this->_expanded[$elt['v']]);
- break;
- }
- $this->_setOpen($elt, $open);
-
- /* Computed values. */
- $ns_info = $this->_getNamespace($elt['v']);
- $tmp = explode(is_null($ns_info) ? $this->_delimiter : $ns_info['delimiter'], $elt['v']);
- $elt['c'] = count($tmp) - 1;
-
- /* Get the mailbox label. */
- $elt['l'] = IMP::getLabel($tmp[$elt['c']]);
-
-
- if ($_SESSION['imp']['protocol'] != 'pop') {
- if (!empty($GLOBALS['conf']['hooks']['display_folder'])) {
- $this->_setInvisible($elt, !Horde::callHook('_imp_hook_display_folder', array($elt['v']), 'imp'));
- }
-
- if ($elt['c'] != 0) {
- $elt['p'] = implode(is_null($ns_info) ? $this->_delimiter : $ns_info['delimiter'], array_slice($tmp, 0, $elt['c']));
- }
-
- if (!is_null($ns_info)) {
- switch ($ns_info['type']) {
- case 'personal':
- /* Strip personal namespace. */
- if (!empty($ns_info['name']) && ($elt['c'] != 0)) {
- --$elt['c'];
- if (strpos($elt['p'], $ns_info['delimiter']) === false) {
- $elt['p'] = self::BASE_ELT;
- } elseif (strpos($elt['v'], $ns_info['name'] . 'INBOX' . $ns_info['delimiter']) === 0) {
- $elt['p'] = 'INBOX';
- }
- }
- break;
-
- case 'other':
- case 'shared':
- if (substr($ns_info['name'], 0, -1 * strlen($ns_info['delimiter'])) == $elt['v']) {
- $elt['a'] = self::ELT_NOSELECT | self::ELT_NAMESPACE;
- }
-
- if ($GLOBALS['prefs']->getValue('tree_view')) {
- $name = ($ns_info['type'] == 'other') ? $this->OTHER_KEY : $this->SHARED_KEY;
- if ($elt['c'] == 0) {
- $elt['p'] = $name;
- ++$elt['c'];
- } elseif ($this->_tree[$name] && self::ELT_NOSHOW) {
- if ($elt['c'] == 1) {
- $elt['p'] = $name;
- }
- } else {
- ++$elt['c'];
- }
- }
- break;
- }
- }
- }
-
- return $elt;
- }
-
- /**
- * Initalize the tree.
- */
- public function init()
- {
- $initmode = (($_SESSION['imp']['protocol'] == 'pop') ||
- !$GLOBALS['prefs']->getValue('subscribe') ||
- $_SESSION['imp']['showunsub'])
- ? 'unsub' : 'sub';
-
- /* Reset class variables to the defaults. */
- $this->_changed = true;
- $this->_currkey = $this->_currparent = $this->_subscribed = null;
- $this->_currstack = $this->_tree = $this->_parent = array();
- $this->_showunsub = $this->_unsubview = ($initmode == 'unsub');
-
- /* Create a placeholder element to the base of the tree list so we can
- * keep track of whether the base level needs to be sorted. */
- $this->_tree[self::BASE_ELT] = array(
- 'a' => self::ELT_NEED_SORT,
- 'v' => self::BASE_ELT
- );
-
- if (empty($GLOBALS['conf']['user']['allow_folders']) ||
- ($_SESSION['imp']['protocol'] == 'pop')) {
- $this->_insertElt($this->_makeElt('INBOX', self::ELT_IS_SUBSCRIBED));
- return;
- }
-
- /* Add namespace elements. */
- foreach ($this->_namespaces as $key => $val) {
- if ($val['type'] != 'personal' &&
- $GLOBALS['prefs']->getValue('tree_view')) {
- $elt = $this->_makeElt(
- ($val['type'] == 'other') ? $this->OTHER_KEY : $this->SHARED_KEY,
- self::ELT_NOSELECT | self::ELT_NAMESPACE | self::ELT_NONIMAP | self::ELT_NOSHOW
- );
- $elt['l'] = ($val['type'] == 'other')
- ? $this->OTHER_LABEL : $this->SHARED_LABEL;
-
- foreach ($this->_namespaces as $val2) {
- if (($val2['type'] == $val['type']) &&
- ($val2['name'] != $val['name'])) {
- $elt['a'] &= ~self::ELT_NOSHOW;
- break;
- }
- }
-
- $this->_insertElt($elt);
- }
- }
-
- /* Create the list (INBOX and all other hierarchies). */
- $this->insert($this->_getList($this->_showunsub));
-
- /* Add virtual folders to the tree. */
- $this->insertVFolders($GLOBALS['imp_search']->listQueries(true));
- }
-
- /**
- * Expand a mail folder.
- *
- * @param string $folder The folder name to expand.
- * @param boolean $expandall Expand all folders under this one?
- */
- public function expand($folder, $expandall = false)
- {
- $folder = $this->_convertName($folder);
-
- if (!isset($this->_tree[$folder])) {
- return;
- }
- $elt = &$this->_tree[$folder];
-
- if ($this->hasChildren($elt)) {
- if (!$this->isOpen($elt)) {
- $this->_changed = true;
- $this->_setOpen($elt, true);
- }
-
- /* Expand all children beneath this one. */
- if ($expandall && !empty($this->_parent[$folder])) {
- foreach ($this->_parent[$folder] as $val) {
- $this->expand($this->_tree[$val]['v'], true);
- }
- }
- }
- }
-
- /**
- * Collapse a mail folder.
- *
- * @param string $folder The folder name to collapse.
- */
- public function collapse($folder)
- {
- $folder = $this->_convertName($folder);
-
- if (!isset($this->_tree[$folder])) {
- return;
- }
-
- if ($this->isOpen($this->_tree[$folder])) {
- $this->_changed = true;
- $this->_setOpen($this->_tree[$folder], false);
- }
- }
-
- /**
- * Sets the internal array pointer to the next element, and returns the
- * next object.
- *
- * @param integer $mask A mask with the following elements:
- * <pre>
- * IMP_IMAP_Tree::NEXT_SHOWCLOSED - Don't ignore closed elements.
- * IMP_IMAP_Tree::NEXT_SHOWSUB - Only show subscribed elements.
- * </pre>
- *
- * @return mixed Returns the next element or false if the element doesn't
- * exist.
- */
- public function next($mask = 0)
- {
- if (is_null($this->_currkey) && is_null($this->_currparent)) {
- return false;
- }
-
- $curr = $this->current();
-
- $old_showunsub = $this->_showunsub;
- if ($mask & self::NEXT_SHOWSUB) {
- $this->_showunsub = false;
- }
-
- if ($this->_activeElt($curr) &&
- (($mask & self::NEXT_SHOWCLOSED) || $this->isOpen($curr)) &&
- ($this->_currparent != $curr['v'])) {
- /* If the current element is open, and children exist, move into
- * it. */
- $this->_currstack[] = array('k' => $this->_currkey, 'p' => $this->_currparent);
- $this->_currkey = 0;
- $this->_currparent = $curr['v'];
- $this->_sortLevel($curr['v']);
-
- $curr = $this->current();
- if ($GLOBALS['prefs']->getValue('tree_view') &&
- $this->isNamespace($curr) &&
- !$this->_isNonIMAPElt($curr) &&
- ($this->_tree[$curr['p']] && self::ELT_NOSHOW)) {
- $this->next($mask);
- }
- } else {
- /* Else, increment within the current subfolder. */
- $this->_currkey++;
- }
-
- $curr = $this->current();
- if (!$curr) {
- if (empty($this->_currstack)) {
- $this->_currkey = $this->_currparent = null;
- $this->_showunsub = $old_showunsub;
- return false;
- } else {
- do {
- $old = array_pop($this->_currstack);
- $this->_currkey = $old['k'] + 1;
- $this->_currparent = $old['p'];
- } while ((($curr = $this->current()) == false) &&
- count($this->_currstack));
- }
- }
-
- $res = $this->_activeElt($curr);
- $this->_showunsub = $old_showunsub;
- return ($res) ? $curr : $this->next($mask);
- }
-
- /**
- * Set internal pointer to the head of the tree.
- * This MUST be called before you can traverse the tree with next().
- *
- * @return mixed Returns the element at the head of the tree or false
- * if the element doesn't exist.
- */
- public function reset()
- {
- $this->_currkey = 0;
- $this->_currparent = self::BASE_ELT;
- $this->_currstack = array();
- $this->_sortLevel($this->_currparent);
- return $this->current();
- }
-
- /**
- * Return the current tree element.
- *
- * @return array The current tree element or false if there is no
- * element.
- */
- public function current()
- {
- return (!isset($this->_parent[$this->_currparent][$this->_currkey]))
- ? false
- : $this->_tree[$this->_parent[$this->_currparent][$this->_currkey]];
- }
-
- /**
- * Determines if there are more elements in the current tree level.
- *
- * @return boolean True if there are more elements, false if this is the
- * last element.
- */
- public function peek()
- {
- for ($i = ($this->_currkey + 1); ; ++$i) {
- if (!isset($this->_parent[$this->_currparent][$i])) {
- return false;
- }
- if ($this->_activeElt($this->_tree[$this->_parent[$this->_currparent][$i]])) {
- return true;
- }
- }
- }
-
- /**
- * Returns the requested element.
- *
- * @param string $name The name of the tree element.
- *
- * @return array Returns the requested element or false if not found.
- */
- public function get($name)
- {
- $name = $this->_convertName($name);
- return (isset($this->_tree[$name])) ? $this->_tree[$name] : false;
- }
-
- /**
- * Insert a folder/mailbox into the tree.
- *
- * @param mixed $id The name of the folder (or a list of folder names)
- * to add.
- */
- public function insert($id)
- {
- if (is_array($id)) {
- /* We want to add from the BASE of the tree up for efficiency
- * sake. */
- $this->_sortList($id);
- } else {
- $id = array($id);
- }
-
- foreach ($id as $val) {
- if (isset($this->_tree[$val]) &&
- !$this->isContainer($this->_tree[$val])) {
- continue;
- }
-
- $ns_info = $this->_getNamespace($val);
- if (is_null($ns_info)) {
- if (strpos($val, $this->VFOLDER_KEY . $this->_delimiter) === 0) {
- $elt = $this->_makeElt($this->VFOLDER_KEY, self::ELT_VFOLDER | self::ELT_NOSELECT | self::ELT_NONIMAP);
- $elt['l'] = $this->VFOLDER_LABEL;
- $this->_insertElt($elt);
- }
-
- $elt = $this->_makeElt($val, self::ELT_VFOLDER | self::ELT_IS_SUBSCRIBED);
- $elt['l'] = $elt['v'] = String::substr($val, String::length($this->VFOLDER_KEY) + String::length($this->_delimiter));
- $this->_insertElt($elt);
- } else {
- /* Break apart the name via the delimiter and go step by
- * step through the name to make sure all subfolders exist
- * in the tree. */
- $parts = explode($ns_info['delimiter'], $val);
- $parts[0] = $this->_convertName($parts[0]);
- $parts_count = count($parts);
- for ($i = 0; $i < $parts_count; ++$i) {
- $part = implode($ns_info['delimiter'], array_slice($parts, 0, $i + 1));
-
- if (isset($this->_tree[$part])) {
- if (($part == $val) &&
- $this->isContainer($this->_tree[$part])) {
- $this->_setContainer($this->_tree[$part], false);
- }
- } else {
- $this->_insertElt(($part == $val) ? $this->_makeElt($part) : $this->_makeElt($part, self::ELT_NOSELECT));
- }
- }
- }
- }
- }
-
- /**
- * Insert an element into the tree.
- *
- * @param array $elt The element to insert. The key in the tree is the
- * 'v' (value) element of the element.
- */
- protected function _insertElt($elt)
- {
- if (!strlen($elt['l']) || isset($this->_tree[$elt['v']])) {
- return;
- }
-
- // UW fix - it may return both 'foo' and 'foo/' as folder names.
- // Only add one of these (without the namespace character) to
- // the tree. See Ticket #5764.
- $ns_info = $this->_getNamespace($elt['v']);
- if (isset($this->_tree[rtrim($elt['v'], is_null($ns_info) ? $this->_delimiter : $ns_info['delimiter'])])) {
- return;
- }
-
- $this->_changed = true;
-
- /* Set the parent array to the value in $elt['p']. */
- if (empty($this->_parent[$elt['p']])) {
- $this->_parent[$elt['p']] = array();
- // This is a case where it is possible that the parent element has
- // changed (it now has children) but we can't catch it via the
- // bitflag (since hasChildren() is dynamically determined).
- if ($this->_trackdiff && !is_null($this->_eltdiff)) {
- $this->_eltdiff['c'][$elt['p']] = 1;
- }
- }
- $this->_parent[$elt['p']][] = $elt['v'];
- $this->_tree[$elt['v']] = $elt;
-
- if ($this->_trackdiff && !is_null($this->_eltdiff)) {
- $this->_eltdiff['a'][$elt['v']] = 1;
- }
-
- /* Make sure we are sorted correctly. */
- if (count($this->_parent[$elt['p']]) > 1) {
- $this->_setNeedSort($this->_tree[$elt['p']], true);
- }
- }
-
- /**
- * Delete an element from the tree.
- *
- * @param mixed $id The element name or an array of element names.
- *
- * @return boolean Return true on success, false on error.
- */
- public function delete($id)
- {
- if (is_array($id)) {
- /* We want to delete from the TOP of the tree down to ensure that
- * parents have an accurate view of what children are left. */
- $this->_sortList($id);
- $id = array_reverse($id);
-
- $success = true;
- foreach ($id as $val) {
- $currsuccess = $this->delete($val);
- if (!$currsuccess) {
- $success = false;
- }
- }
- return $success;
- } else {
- $id = $this->_convertName($id, true);
- }
-
- $vfolder_base = ($id == $this->VFOLDER_LABEL);
- $search_id = $GLOBALS['imp_search']->createSearchID($id);
-
- if ($vfolder_base ||
- (isset($this->_tree[$search_id]) &&
- $this->isVFolder($this->_tree[$search_id]))) {
- if (!$vfolder_base) {
- $id = $search_id;
-
- }
- $parent = $this->_tree[$id]['p'];
- unset($this->_tree[$id]);
-
- /* Delete the entry from the parent tree. */
- $key = array_search($id, $this->_parent[$parent]);
- unset($this->_parent[$parent][$key]);
-
- /* Rebuild the parent tree. */
- if (!$vfolder_base && empty($this->_parent[$parent])) {
- $this->delete($parent);
- } else {
- $this->_parent[$parent] = array_values($this->_parent[$parent]);
- }
- $this->_changed = true;
-
- return true;
- }
-
- $ns_info = $this->_getNamespace($id);
-
- if (($id == 'INBOX') ||
- !isset($this->_tree[$id]) ||
- ($id == $ns_info['name'])) {
- return false;
- }
-
- $this->_changed = true;
-
- $elt = &$this->_tree[$id];
-
- /* Do not delete from tree if there are child elements - instead,
- * convert to a container element. */
- if ($this->hasChildren($elt)) {
- $this->_setContainer($elt, true);
- return true;
- }
-
- $parent = $elt['p'];
-
- /* Delete the tree entry. */
- unset($this->_tree[$id]);
-
- /* Delete the entry from the parent tree. */
- $key = array_search($id, $this->_parent[$parent]);
- unset($this->_parent[$parent][$key]);
-
- if (!is_null($this->_eltdiff)) {
- $this->_eltdiff['d'][$id] = 1;
- }
-
- if (empty($this->_parent[$parent])) {
- /* This folder is now completely empty (no children). If the
- * folder is a container only, we should delete the folder from
- * the tree. */
- unset($this->_parent[$parent]);
- if (isset($this->_tree[$parent])) {
- if ($this->isContainer($this->_tree[$parent]) &&
- !$this->isNamespace($this->_tree[$parent])) {
- $this->delete($parent);
- } else {
- $this->_modifyExpandedList($parent, 'remove');
- $this->_setOpen($this->_tree[$parent], false);
- /* This is a case where it is possible that the parent
- * element has changed (it no longer has children) but
- * we can't catch it via the bitflag (since hasChildren()
- * is dynamically determined). */
- if (!is_null($this->_eltdiff)) {
- $this->_eltdiff['c'][$parent] = 1;
- }
- }
- }
- } else {
- /* Rebuild the parent tree. */
- $this->_parent[$parent] = array_values($this->_parent[$parent]);
- }
-
- /* Remove the mailbox from the expanded folders list. */
- $this->_modifyExpandedList($id, 'remove');
-
- /* Remove the mailbox from the nav_poll list. */
- $this->removePollList($id);
-
- return true;
- }
-
- /**
- * Subscribe an element to the tree.
- *
- * @param mixed $id The element name or an array of element names.
- */
- public function subscribe($id)
- {
- if (!is_array($id)) {
- $id = array($id);
- }
-
- foreach ($id as $val) {
- $val = $this->_convertName($val);
- if (isset($this->_tree[$val])) {
- $this->_changed = true;
- $this->_setSubscribed($this->_tree[$val], true);
- $this->_setContainer($this->_tree[$val], false);
- }
- }
- }
-
- /**
- * Unsubscribe an element from the tree.
- *
- * @param mixed $id The element name or an array of element names.
- */
- public function unsubscribe($id)
- {
- if (!is_array($id)) {
- $id = array($id);
- } else {
- /* We want to delete from the TOP of the tree down to ensure that
- * parents have an accurate view of what children are left. */
- $this->_sortList($id);
- $id = array_reverse($id);
- }
-
- foreach ($id as $val) {
- $val = $this->_convertName($val);
-
- /* INBOX can never be unsubscribed to. */
- if (isset($this->_tree[$val]) && ($val != 'INBOX')) {
- $this->_changed = $this->_unsubview = true;
-
- $elt = &$this->_tree[$val];
-
- /* Do not delete from tree if there are child elements -
- * instead, convert to a container element. */
- if (!$this->_showunsub && $this->hasChildren($elt)) {
- $this->_setContainer($elt, true);
- }
-
- /* Set as unsubscribed, add to unsubscribed list, and remove
- * from subscribed list. */
- $this->_setSubscribed($elt, false);
- }
- }
- }
-
- /**
- * Set an attribute for an element.
- *
- * @param array &$elt The tree element.
- * @param integer $const The constant to set/remove from the bitmask.
- * @param boolean $bool Should the attribute be set?
- */
- protected function _setAttribute(&$elt, $const, $bool)
- {
- if ($bool) {
- $elt['a'] |= $const;
- } else {
- $elt['a'] &= ~$const;
- }
- }
-
- /**
- * Does the element have any active children?
- *
- * @param array $elt A tree element.
- *
- * @return boolean True if the element has active children.
- */
- public function hasChildren($elt)
- {
- if (isset($this->_parent[$elt['v']])) {
- if ($this->_showunsub) {
- return true;
- }
-
- foreach ($this->_parent[$elt['v']] as $val) {
- $child = &$this->_tree[$val];
- if ($this->isSubscribed($child) ||
- $this->hasChildren($this->_tree[$val])) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Is the tree element open?
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the element is open.
- */
- public function isOpen($elt)
- {
- return (($elt['a'] & self::ELT_IS_OPEN) && $this->hasChildren($elt));
- }
-
- /**
- * Set the open attribute for an element.
- *
- * @param array &$elt A tree element.
- * @param boolean $bool The setting.
- */
- protected function _setOpen(&$elt, $bool)
- {
- $this->_setAttribute($elt, self::ELT_IS_OPEN, $bool);
- $this->_modifyExpandedList($elt['v'], $bool ? 'add' : 'remove');
- }
-
- /**
- * Is this element a container only, not a mailbox (meaning you can
- * not open it)?
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the element is a container.
- */
- public function isContainer($elt)
- {
- return (($elt['a'] & self::ELT_NOSELECT) ||
- (!$this->_showunsub &&
- !$this->isSubscribed($elt) &&
- $this->hasChildren($elt)));
- }
-
- /**
- * Set the element as a container?
- *
- * @param array &$elt A tree element.
- * @param boolean $bool Is the element a container?
- */
- protected function _setContainer(&$elt, $bool)
- {
- $this->_setAttribute($elt, self::ELT_NOSELECT, $bool);
- }
-
- /**
- * Is the user subscribed to this element?
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the user is subscribed to the element.
- */
- public function isSubscribed($elt)
- {
- return $elt['a'] & self::ELT_IS_SUBSCRIBED;
- }
-
- /**
- * Set the subscription status for an element.
- *
- * @param array &$elt A tree element.
- * @param boolean $bool Is the element subscribed to?
- */
- protected function _setSubscribed(&$elt, $bool)
- {
- $this->_setAttribute($elt, self::ELT_IS_SUBSCRIBED, $bool);
- if (!is_null($this->_subscribed)) {
- if ($bool) {
- $this->_subscribed[$elt['v']] = 1;
- } else {
- unset($this->_subscribed[$elt['v']]);
- }
- }
- }
-
- /**
- * Is the element a namespace container?
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the element is a namespace container.
- */
- public function isNamespace($elt)
- {
- return $elt['a'] & self::ELT_NAMESPACE;
- }
-
- /**
- * Is the element a non-IMAP element?
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the element is a non-IMAP element.
- */
- protected function _isNonIMAPElt($elt)
- {
- return $elt['a'] & self::ELT_NONIMAP;
- }
-
- /**
- * Initialize the expanded folder list.
- */
- protected function _initExpandedList()
- {
- if (is_null($this->_expanded)) {
- $serialized = $GLOBALS['prefs']->getValue('expanded_folders');
- $this->_expanded = ($serialized) ? unserialize($serialized) : array();
- }
- }
-
- /**
- * Add/remove an element to the expanded list.
- *
- * @param string $id The element name to add/remove.
- * @param string $action Either 'add' or 'remove';
- */
- protected function _modifyExpandedList($id, $action)
- {
- $this->_initExpandedList();
- if ($action == 'add') {
- $this->_expanded[$id] = true;
- } else {
- unset($this->_expanded[$id]);
- }
- $GLOBALS['prefs']->setValue('expanded_folders', serialize($this->_expanded));
- }
-
- /**
- * Initializes and returns the list of mailboxes to poll.
- *
- * @param boolean $prune Prune non-existant folders from list?
- * @param boolean $sort Sort the directory list?
- *
- * @return array The list of mailboxes to poll.
- */
- public function getPollList($prune = false, $sort = false)
- {
- $this->_initPollList();
-
- $plist = ($prune) ? array_values(array_intersect(array_keys($this->_poll), $this->folderList())) : $this->_poll;
- if ($sort) {
- $ns_new = $this->_getNamespace(null);
- Horde_Imap_Client_Sort::sortMailboxes($plist, array('delimiter' => $ns_new['delimiter'], 'inbox' => true));
- }
-
- return $plist;
- }
-
- /**
- * Init the poll list. Called once per session.
- */
- protected function _initPollList()
- {
- if (is_null($this->_poll)) {
- /* We ALWAYS poll the INBOX. */
- $this->_poll = array('INBOX' => 1);
-
- /* Add the list of polled mailboxes from the prefs. */
- if ($GLOBALS['prefs']->getValue('nav_poll_all')) {
- $navPollList = array_flip($this->_getList(true));
- } else {
- $old_error = error_reporting(0);
- $navPollList = unserialize($GLOBALS['prefs']->getValue('nav_poll'));
- error_reporting($old_error);
- }
- if ($navPollList) {
- $this->_poll += $navPollList;
- }
- }
- }
-
- /**
- * Add element to the poll list.
- *
- * @param mixed $id The element name or a list of element names to add.
- */
- public function addPollList($id)
- {
- if (!is_array($id)) {
- $id = array($id);
- }
-
- if (!empty($id) && !$GLOBALS['prefs']->isLocked('nav_poll')) {
- $imp_folder = IMP_Folder::singleton();
- $this->getPollList();
- foreach ($id as $val) {
- if (!$this->isSubscribed($this->_tree[$val])) {
- $imp_folder->subscribe(array($val));
- }
- $this->_poll[$val] = true;
- $this->_setPolled($this->_tree[$val], true);
- }
- $GLOBALS['prefs']->setValue('nav_poll', serialize($this->_poll));
- $this->_changed = true;
- }
- }
-
- /**
- * Remove element from the poll list.
- *
- * @param string $id The folder/mailbox or a list of folders/mailboxes
- * to remove.
- */
- public function removePollList($id)
- {
- if (!is_array($id)) {
- $id = array($id);
- }
-
- $removed = false;
-
- if (!$GLOBALS['prefs']->isLocked('nav_poll')) {
- $this->getPollList();
- foreach ($id as $val) {
- if ($val != 'INBOX') {
- unset($this->_poll[$val]);
- if (isset($this->_tree[$val])) {
- $this->_setPolled($this->_tree[$val], false);
- }
- $removed = true;
- }
- }
- if ($removed) {
- $GLOBALS['prefs']->setValue('nav_poll', serialize($this->_poll));
- $this->_changed = true;
- }
- }
- }
-
- /**
- * Does the user want to poll this mailbox for new/unseen messages?
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the user wants to poll the element.
- */
- public function isPolled($elt)
- {
- return ($GLOBALS['prefs']->getValue('nav_poll_all')) ? true : ($elt['a'] & self::ELT_IS_POLLED);
- }
-
- /**
- * Set the polled attribute for an element.
- *
- * @param array &$elt A tree element.
- * @param boolean $bool The setting.
- */
- protected function _setPolled(&$elt, $bool)
- {
- $this->_setAttribute($elt, self::ELT_IS_POLLED, $bool);
- }
-
- /**
- * Is the element invisible?
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the element is marked as invisible.
- */
- public function isInvisible($elt)
- {
- return $elt['a'] & self::ELT_INVISIBLE;
- }
-
- /**
- * Set the invisible attribute for an element.
- *
- * @param array &$elt A tree element.
- * @param boolean $bool The setting.
- */
- protected function _setInvisible(&$elt, $bool)
- {
- $this->_setAttribute($elt, self::ELT_INVISIBLE, $bool);
- }
-
- /**
- * Flag the element as needing its children to be sorted.
- *
- * @param array &$elt A tree element.
- * @param boolean $bool The setting.
- */
- protected function _setNeedSort(&$elt, $bool)
- {
- $this->_setAttribute($elt, self::ELT_NEED_SORT, $bool);
- }
-
- /**
- * Does this element's children need sorting?
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the children need to be sorted.
- */
- protected function _needSort($elt)
- {
- return (($elt['a'] & self::ELT_NEED_SORT) && (count($this->_parent[$elt['v']]) > 1));
- }
-
- /**
- * Initialize the list of subscribed mailboxes.
- */
- protected function _initSubscribed()
- {
- if (is_null($this->_subscribed)) {
- $this->_getList(false);
- }
- }
-
- /**
- * Should we expand all elements?
- */
- public function expandAll()
- {
- foreach ($this->_parent[self::BASE_ELT] as $val) {
- $this->expand($val, true);
- }
- }
-
- /**
- * Should we collapse all elements?
- */
- public function collapseAll()
- {
- foreach ($this->_tree as $key => $val) {
- if ($key !== self::BASE_ELT) {
- $this->collapse($val['v']);
- }
- }
- }
-
- /**
- * Switch subscribed/unsubscribed viewing.
- *
- * @param boolean $unsub Show unsubscribed elements?
- */
- public function showUnsubscribed($unsub)
- {
- if ((bool)$unsub === $this->_showunsub) {
- return;
- }
-
- $this->_showunsub = $unsub;
- $this->_changed = true;
-
- /* If we are switching from unsubscribed to subscribed, no need
- * to do anything (we just ignore unsubscribed stuff). */
- if ($unsub === false) {
- return;
- }
-
- /* If we are switching from subscribed to unsubscribed, we need
- * to add all unsubscribed elements that live in currently
- * discovered items. */
- $this->_unsubview = true;
- $this->_trackdiff = false;
- $this->insert($this->_getList(true));
- $this->_trackdiff = true;
- }
-
- /**
- * Get information about new/unseen/total messages for the given element.
- *
- * @param string $name The element name (UTF7-IMAP).
- *
- * @return array Array with the following fields:
- * <pre>
- * 'messages' - (integer) Number of total messages.
- * 'recent' - (integer) Number of new messages.
- * 'unseen' - (integer) Number of unseen messages.
- * </pre>
- */
- public function getElementInfo($name)
- {
- try {
- return $GLOBALS['imp_imap']->ob->status($name, Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_RECENT | Horde_Imap_Client::STATUS_UNSEEN);
- } catch (Horde_Imap_Client_Exception $e) {
- return array();
- }
- }
-
- /**
- * Sorts a list of mailboxes.
- *
- * @param array &$mbox The list of mailboxes to sort.
- * @param boolean $base Are we sorting a list of mailboxes in the base
- * of the tree.
- */
- protected function _sortList(&$mbox, $base = false)
- {
- $config_array = array(
- 'delimiter' => $this->_delimiter,
- 'inbox' => true
- );
-
- if ($base) {
- $basesort = array();
- foreach ($mbox as $val) {
- $basesort[$val] = ($val == 'INBOX') ? 'INBOX' : $this->_tree[$val]['l'];
- }
- $config_array['index'] = true;
- Horde_Imap_Client_Sort::sortMailboxes($basesort, $config_array);
- $mbox = array_keys($basesort);
- } else {
- Horde_Imap_Client_Sort::sortMailboxes($mbox, $config_array);
- }
-
- if ($base) {
- for ($i = 0, $count = count($mbox); $i < $count; ++$i) {
- if ($this->_isNonIMAPElt($this->_tree[$mbox[$i]])) {
- /* Already sorted by name - simply move to the end of
- * the array. */
- $mbox[] = $mbox[$i];
- unset($mbox[$i]);
- }
- }
- $mbox = array_values($mbox);
- }
- }
-
- /**
- * Is the given element an "active" element (i.e. an element that should
- * be worked with given the current viewing parameters).
- *
- * @param array $elt A tree element.
- *
- * @return boolean True if it is an active element.
- */
- protected function _activeElt($elt)
- {
- return (!$this->isInvisible($elt) &&
- ($this->_showunsub ||
- ($this->isSubscribed($elt) && !$this->isContainer($elt)) ||
- $this->hasChildren($elt)));
- }
-
- /**
- * Convert a mailbox name to the correct, internal name (i.e. make sure
- * INBOX is always capitalized for IMAP servers).
- *
- * @param string $name The mailbox name.
- *
- * @return string The converted name.
- */
- protected function _convertName($name)
- {
- return (strcasecmp($name, 'INBOX') == 0) ? 'INBOX' : $name;
- }
-
- /**
- * Get namespace info for a full folder path.
- *
- * @param string $mailbox The folder path.
- *
- * @return mixed The namespace info for the folder path or null if the
- * path doesn't exist.
- */
- protected function _getNamespace($mailbox)
- {
- if (!in_array($mailbox, array($this->OTHER_KEY, $this->SHARED_KEY, $this->VFOLDER_KEY)) &&
- (strpos($mailbox, $this->VFOLDER_KEY . $this->_delimiter) !== 0)) {
- return $GLOBALS['imp_imap']->getNamespace($mailbox);
- }
- return null;
- }
-
- /**
- * Set the start point for determining element differences via eltDiff().
- */
- public function eltDiffStart()
- {
- $this->_eltdiff = array('a' => array(), 'c' => array(), 'd' => array());
- }
-
- /**
- * Return the list of elements that have changed since eltDiffStart()
- * was last called.
- *
- * @return array Returns false if no changes have occurred, or an array
- * with the following keys:
- * <pre>
- * 'a' => A list of elements that have been added.
- * 'c' => A list of elements that have been changed.
- * 'd' => A list of elements that have been deleted.
- * </pre>
- */
- public function eltDiff()
- {
- if (is_null($this->_eltdiff) || !$this->_changed) {
- return false;
- }
-
- $ret = array(
- 'a' => array_keys($this->_eltdiff['a']),
- 'c' => array_keys($this->_eltdiff['c']),
- 'd' => array_keys($this->_eltdiff['d'])
- );
-
- $this->_eltdiff = null;
-
- return $ret;
- }
-
- /**
- * Inserts virtual folders into the tree.
- *
- * @param array $id_list An array with the folder IDs to add as the key
- * and the labels as the value.
- */
- public function insertVFolders($id_list)
- {
- if (empty($id_list) ||
- empty($GLOBALS['conf']['user']['allow_folders'])) {
- return;
- }
-
- $adds = $id = array();
-
- foreach ($id_list as $key => $val) {
- $id[$GLOBALS['imp_search']->createSearchID($key)] = $val;
- }
-
- foreach (array_keys($id) as $key) {
- $id_key = $this->VFOLDER_KEY . $this->_delimiter . $key;
- if (!isset($this->_tree[$id_key])) {
- $adds[] = $id_key;
- }
- }
-
- if (empty($adds)) {
- return;
- }
-
- $this->insert($adds);
-
- foreach ($id as $key => $val) {
- $this->_tree[$key]['l'] = $val;
- }
-
- /* Sort the Virtual Folder list in the object, if necessary. */
- if ($this->_needSort($this->_tree[$this->VFOLDER_KEY])) {
- $vsort = array();
- foreach ($this->_parent[$this->VFOLDER_KEY] as $val) {
- $vsort[$val] = $this->_tree[$val]['l'];
- }
- natcasesort($vsort);
- $this->_parent[$this->VFOLDER_KEY] = array_keys($vsort);
- $this->_setNeedSort($this->_tree[$this->VFOLDER_KEY], false);
- $this->_changed = true;
- }
- }
-
- /**
- * Builds a list of folders, suitable to render a folder tree.
- *
- * @param integer $mask The mask to pass to next().
- * @param boolean $open If using the base folder icons, display a
- * different icon whether the folder is opened or
- * closed.
- *
- * @return array An array with three elements: the folder list, the total
- * number of new messages, and a list with folder names
- * suitable for user interaction.
- * The folder list array contains the following added
- * entries on top of the entries provided by element():
- * <pre>
- * 'display' - The mailbox name run through IMP::displayFolder().
- * 'peek' - See peek().
- * </pre>
- */
- public function build($mask = 0, $open = true)
- {
- $displayNames = $newmsgs = $rows = array();
- $this->_forceopen = $open;
-
- /* Start iterating through the list of mailboxes, displaying them. */
- $mailbox = $this->reset();
- do {
- $row = $this->element($mailbox['v']);
-
- $row['display'] = ($this->_isNonIMAPElt($mailbox)) ? $mailbox['l'] : IMP::displayFolder($mailbox['v']);
- $row['peek'] = $this->peek();
-
- if (!empty($row['recent'])) {
- $newmsgs[$row['value']] = $row['recent'];
- }
-
- /* Hide folder prefixes from the user. */
- if ($row['level'] >= 0) {
- $rows[] = $row;
- $displayNames[] = addslashes($row['display']);
- }
- } while (($mailbox = $this->next($mask)));
-
- $this->_forceopen = false;
-
- return array($rows, $newmsgs, $displayNames);
- }
-
- /**
- * Get any custom icon configured for the given element.
- *
- * @params array $elt A tree element.
- *
- * @return array An array with the 'icon', 'icondir', and 'alt'
- * information for the element, or false if no icon
- * available.
- */
- public function getCustomIcon($elt)
- {
- static $mbox_icons;
-
- if (isset($mbox_icons) && !$mbox_icons) {
- return false;
- }
-
- /* Call the mailbox icon hook, if requested. */
- if (empty($GLOBALS['conf']['hooks']['mbox_icon'])) {
- $mbox_icons = false;
- return false;
- }
-
- if (!isset($mbox_icons)) {
- $mbox_icons = Horde::callHook('_imp_hook_mbox_icons', array(), 'imp', false);
- if (!$mbox_icons) {
- return false;
- }
- }
-
- if (isset($mbox_icons[$elt['v']])) {
- return array('icon' => $mbox_icons[$elt['v']]['icon'], 'icondir' => $mbox_icons[$elt['v']]['icondir'], 'alt' => $mbox_icons[$elt['v']]['alt']);
- }
-
- return false;
- }
-
- /**
- * Returns whether this element is a virtual folder.
- *
- * @param array $elt A tree element.
- *
- * @return integer True if the element is a virtual folder.
- */
- public function isVFolder($elt)
- {
- return $elt['a'] & self::ELT_VFOLDER;
- }
-
- /**
- * Rename a current folder.
- *
- * @param array $old The old folder names.
- * @param array $new The new folder names.
- */
- public function rename($old, $new)
- {
- foreach ($old as $key => $val) {
- $polled = (isset($this->_tree[$val])) ? $this->isPolled($this->_tree[$val]) : false;
- if ($this->delete($val)) {
- $this->insert($new[$key]);
- if ($polled) {
- $this->addPollList($new[$key]);
- }
- }
- }
- }
-
- /**
- * Returns a list of all IMAP mailboxes in the tree.
- *
- * @param integer $mask A mask with the following elements:
- * <pre>
- * IMP_IMAP_Tree::FLIST_CONTAINER - Show container elements.
- * IMP_IMAP_Tree::FLIST_UNSUB - Show unsubscribed elements.
- * IMP_IMAP_Tree::FLIST_OB - Return full tree object.
- * IMP_IMAP_Tree::FLIST_VFOLDER - Show Virtual Folders.
- * </pre>
- * @param string $base Return all mailboxes below this element.
- *
- * @return array An array of IMAP mailbox names.
- */
- public function folderList($mask = 0, $base = null)
- {
- $baseindex = null;
- $ret_array = array();
-
- $diff_unsub = (($mask & self::FLIST_UNSUB) != $this->_showunsub) ? $this->_showunsub : null;
- $this->showUnsubscribed($mask & self::FLIST_UNSUB);
-
- $mailbox = $this->reset();
-
- // Search to base element.
- if (!is_null($base)) {
- while ($mailbox && $mailbox['v'] != $base) {
- $mailbox = $this->next(self::NEXT_SHOWCLOSED);
- }
- if ($mailbox) {
- $baseindex = count($this->_currstack);
- $baseparent = $this->_currparent;
- $basekey = $this->_currkey;
- $mailbox = $this->next(self::NEXT_SHOWCLOSED);
- }
- }
-
- if ($mailbox) {
- do {
- if (!is_null($baseindex) &&
- (!isset($this->_currstack[$baseindex]) ||
- ($this->_currstack[$baseindex]['k'] != $basekey) ||
- ($this->_currstack[$baseindex]['p'] != $baseparent))) {
- break;
- }
-
- if ((($mask & self::FLIST_CONTAINER) ||
- !$this->isContainer($mailbox)) &&
- (($mask & self::FLIST_VFOLDER) ||
- !$this->isVFolder($mailbox))) {
- $ret_array[] = ($mask & self::FLIST_OB) ? $mailbox : $mailbox['v'];
- }
- } while (($mailbox = $this->next(self::NEXT_SHOWCLOSED)));
- }
-
- if (!is_null($diff_unsub)) {
- $this->showUnsubscribed($diff_unsub);
- }
-
- return $ret_array;
- }
-
- /**
- * Is the mailbox open in the sidebar?
- *
- * @param array $mbox A mailbox name.
- *
- * @return integer True if the mailbox is open in the sidebar.
- */
- public function isOpenSidebar($mbox)
- {
- switch ($GLOBALS['prefs']->getValue('nav_expanded_sidebar')) {
- case self::OPEN_USER:
- $this->_initExpandedList();
- return !empty($this->_expanded[$mbox]);
- break;
-
- case self::OPEN_ALL:
- return true;
- break;
-
- case self::OPEN_NONE:
- default:
- return false;
- break;
- }
- }
-
- /**
- * Init frequently used element() data.
- */
- protected function _initElement()
- {
- global $prefs, $registry;
-
- /* Initialize the user's identities. */
- require_once 'Horde/Identity.php';
- $identity = Identity::singleton(array('imp', 'imp'));
-
- return array(
- 'trash' => IMP::folderPref($prefs->getValue('trash_folder'), true),
- 'draft' => IMP::folderPref($prefs->getValue('drafts_folder'), true),
- 'spam' => IMP::folderPref($prefs->getValue('spam_folder'), true),
- 'sent' => $identity->getAllSentmailFolders(),
- 'image_dir' => $registry->getImageDir(),
- );
- }
-
- /**
- * Return extended information on an element.
- *
- * @param string $name The name of the tree element.
- *
- * @return array Returns the element with extended information, or false
- * if not found. The information returned is as follows:
- * <pre>
- * 'alt' - The alt text for the icon.
- * 'base_elt' - The return from get().
- * 'children' - Does the element have children?
- * 'container' - Is this a container element?
- * 'editvfolder' - Can this virtual folder be edited?
- * 'icon' - The name of the icon graphic to use.
- * 'icondir' - The path of the icon directory.
- * 'level' - The deepness level of this element.
- * 'mbox_val' - A html-ized version of 'value'.
- * 'msgs' - The number of total messages in the element (if polled).
- * 'name' - A html-ized version of 'label'.
- * 'parent' - The parent element value.
- * 'polled' - Show polled information?
- * 'recent' - The number of new messages in the element (if polled).
- * 'special' - An integer mask indicating if this is a "special" element.
- * 'specialvfolder' - Is this a "special" virtual folder?
- * 'unseen' - The number of unseen messages in the element (if polled).
- * 'user_icon' - Use a user defined icon?
- * 'value' - The value of this element (i.e. element id).
- * 'vfolder' - Is this a virtual folder?
- * </pre>
- */
- public function element($mailbox)
- {
- static $elt;
-
- $mailbox = $this->get($mailbox);
- if (!$mailbox) {
- return false;
- }
-
- if (!isset($elt)) {
- $elt = $this->_initElement();
- }
-
- $row = array(
- 'base_elt' => $mailbox,
- 'children' => $this->hasChildren($mailbox),
- 'container' => false,
- 'editvfolder' => false,
- 'icondir' => $elt['image_dir'],
- 'iconopen' => null,
- 'level' => $mailbox['c'],
- 'mbox_val' => htmlspecialchars($mailbox['v']),
- 'name' => htmlspecialchars($mailbox['l']),
- 'parent' => $mailbox['p'],
- 'polled' => false,
- 'recent' => 0,
- 'special' => 0,
- 'specialvfolder' => false,
- 'user_icon' => false,
- 'value' => $mailbox['v'],
- 'vfolder' => false,
- );
-
- $icon = $this->getCustomIcon($mailbox);
-
- if (!$this->isContainer($mailbox)) {
- /* We are dealing with mailboxes here.
- * Determine if we need to poll this mailbox for new messages. */
- if ($this->isPolled($mailbox)) {
- /* If we need message information for this folder, update
- * it now. */
- $msgs_info = $this->getElementInfo($mailbox['v']);
- if (!empty($msgs_info)) {
- $row['polled'] = true;
- if (!empty($msgs_info['recent'])) {
- $row['recent'] = $msgs_info['recent'];
- }
- $row['msgs'] = $msgs_info['messages'];
- $row['unseen'] = $msgs_info['unseen'];
- }
- }
-
-
- switch ($mailbox['v']) {
- case 'INBOX':
- $row['icon'] = 'folders/inbox.png';
- $row['alt'] = _("Inbox");
- $row['special'] = self::SPECIAL_INBOX;
- break;
-
- case $elt['trash']:
- if ($GLOBALS['prefs']->getValue('use_vtrash')) {
- $row['icon'] = ($this->isOpen($mailbox)) ? 'folders/folder_open.png' : 'folders/folder.png';
- $row['alt'] = _("Mailbox");
- } else {
- $row['icon'] = 'folders/trash.png';
- $row['alt'] = _("Trash folder");
- $row['special'] = self::SPECIAL_TRASH;
- }
- break;
-
- case $elt['draft']:
- $row['icon'] = 'folders/drafts.png';
- $row['alt'] = _("Draft folder");
- $row['special'] = self::SPECIAL_DRAFT;
- break;
-
- case $elt['spam']:
- $row['icon'] = 'folders/spam.png';
- $row['alt'] = _("Spam folder");
- $row['special'] = self::SPECIAL_SPAM;
- break;
-
- default:
- if (in_array($mailbox['v'], $elt['sent'])) {
- $row['icon'] = 'folders/sent.png';
- $row['alt'] = _("Sent mail folder");
- $row['special'] = self::SPECIAL_SENT;
- } else {
- $row['icon'] = ($this->isOpen($mailbox)) ? 'folders/folder_open.png' : 'folders/folder.png';
- $row['alt'] = _("Mailbox");
- }
- break;
- }
-
- /* Virtual folders. */
- if ($this->isVFolder($mailbox)) {
- $row['vfolder'] = true;
- $row['editvfolder'] = $GLOBALS['imp_search']->isEditableVFolder($mailbox['v']);
- if ($GLOBALS['imp_search']->isVTrashFolder($mailbox['v'])) {
- $row['specialvfolder'] = true;
- $row['icon'] = 'folders/trash.png';
- $row['alt'] = _("Virtual Trash Folder");
- } elseif ($GLOBALS['imp_search']->isVINBOXFolder($mailbox['v'])) {
- $row['specialvfolder'] = true;
- $row['icon'] = 'folders/inbox.png';
- $row['alt'] = _("Virtual INBOX Folder");
- }
- }
- } else {
- /* We are dealing with folders here. */
- $row['container'] = true;
- if ($this->_forceopen && $this->isOpen($mailbox)) {
- $row['icon'] = 'folders/folder_open.png';
- $row['alt'] = _("Opened Folder");
- } else {
- $row['icon'] = 'folders/folder.png';
- $row['iconopen'] = 'folders/folder_open.png';
- $row['alt'] = ($this->_forceopen) ? _("Closed Folder") : _("Folder");
- }
- if ($this->isVFolder($mailbox)) {
- $row['vfolder'] = true;
- }
- }
-
- /* Overwrite the icon information now. */
- if (!empty($icon)) {
- $row['icon'] = $icon['icon'];
- $row['icondir'] = $icon['icondir'];
- if (!empty($icon['alt'])) {
- $row['alt'] = $icon['alt'];
- }
- $row['iconopen'] = isset($icon['iconopen']) ? $icon['iconopen'] : null;
- $row['user_icon'] = true;
- }
-
- return $row;
- }
-
- /**
- * Sort a level in the tree.
- *
- * @param string $id The parent folder whose children need to be sorted.
- */
- protected function _sortLevel($id)
- {
- if ($this->_needSort($this->_tree[$id])) {
- $this->_sortList($this->_parent[$id], ($id === self::BASE_ELT));
- $this->_setNeedSort($this->_tree[$id], false);
- $this->_changed = true;
- }
- }
-
- /**
- * Determines the mailbox name to create given a parent and the new name.
- *
- * @param string $parent The parent name (UTF7-IMAP).
- * @param string $parent The new mailbox name (UTF7-IMAP).
- *
- * @return string The full path to the new mailbox.
- * @throws Horde_Exception
- */
- public function createMailboxName($parent, $new)
- {
- $ns_info = (empty($parent)) ? $GLOBALS['imp_imap']->defaultNamespace() : $this->_getNamespace($parent);
- if (is_null($ns_info)) {
- if ($this->isNamespace($this->_tree[$parent])) {
- $ns_info = $this->_getNamespace($new);
- if (in_array($ns_info['type'], array('other', 'shared'))) {
- return $new;
- }
- }
- throw new Horde_Exception(_("Cannot directly create mailbox in this folder."), 'horde.error');
- }
-
- $mbox = $ns_info['name'];
- if (!empty($parent)) {
- $mbox .= substr_replace($parent, '', 0, strlen($ns_info['name']));
- $mbox = rtrim($mbox, $ns_info['delimiter']) . $ns_info['delimiter'];
- }
- return $mbox . $new;
- }
-}
--- /dev/null
+<?php
+/**
+ * The IMP_Imap:: class provides common functions for interaction with the
+ * IMAP/POP3 server via the Horde_Imap_Client:: library.
+ *
+ * Copyright 2008-2009 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_Imap
+{
+ /**
+ * The Horde_Imap_Client object.
+ *
+ * @var Horde_Imap_Client
+ */
+ public $ob = null;
+
+ /**
+ * The Horde_Imap_Client_Utils object.
+ *
+ * @var Horde_Imap_Client_Utils
+ */
+ public $utils = null;
+
+ /**
+ * Is connection read-only?
+ *
+ * @var array
+ */
+ protected $_readonly = array();
+
+ /**
+ * Namespace cache.
+ *
+ * @var array
+ */
+ protected $_nscache = array();
+
+ /**
+ * Default namespace.
+ *
+ * @var array
+ */
+ protected $_nsdefault;
+
+ /**
+ * Constructor.
+ */
+ function __construct()
+ {
+ /* Register the logging callback. */
+ Horde_Imap_Client_Exception::$logCallback = array($this, 'logException');
+
+ /* Rebuild the Horde_Imap_Client object. */
+ $this->_loadImapObject();
+
+ $this->utils = new Horde_Imap_Client_Utils();
+ }
+
+ /**
+ * Save the Horde_Imap_Client object on session shutdown.
+ */
+ function __destruct()
+ {
+ /* Only need to serialize object once a second. When we do serialize,
+ * make sure we login in order to ensure we have done the necessary
+ * initialization. */
+ if ($this->ob &&
+ isset($_SESSION['imp']) &&
+ !isset($_SESSION['imp']['imap_ob'])) {
+ $this->ob->login();
+ $_SESSION['imp']['imap_ob'] = serialize($this->ob);
+ }
+ }
+
+ /**
+ * Loads the server configuration from servers.php.
+ *
+ * @param string $server Returns this labeled entry only.
+ *
+ * @return mixed If $server is set, then return this entry, or return the
+ * entire servers array. Returns false on error.
+ */
+ static public function loadServerConfig($server = null)
+ {
+ $servers = Horde::loadConfiguration('servers.php', 'servers', 'imp');
+ if (is_a($servers, 'PEAR_Error')) {
+ Horde::logMessage($servers, __FILE__, __LINE__, PEAR_LOG_ERR);
+ return false;
+ }
+
+ if (is_null($server)) {
+ return $servers;
+ }
+
+ /* Check for the existence of the server in the config file. */
+ if (empty($servers[$server]) || !is_array($servers[$server])) {
+ $entry = sprintf('Invalid server key "%s" from client [%s]', $server, $_SERVER['REMOTE_ADDR']);
+ Horde::logMessage($entry, __FILE__, __LINE__, PEAR_LOG_ERR);
+ return false;
+ }
+
+ return $servers[$server];
+ }
+
+ /**
+ * Loads the Horde_Imap_Client object from serialized session data and
+ * loads the object into the global $imp_imap variable.
+ *
+ * @return boolean True on success, false on error.
+ */
+ protected function _loadImapObject()
+ {
+ if (!is_null($this->ob)) {
+ return true;
+ }
+
+ if (!isset($_SESSION['imp']['imap_ob'])) {
+ return false;
+ }
+
+ Horde_Imap_Client::$encryptKey = IMP::getAuthKey();
+
+ $old_error = error_reporting(0);
+ $this->ob = unserialize($_SESSION['imp']['imap_ob']);
+ error_reporting($old_error);
+
+ if (empty($this->ob)) {
+ // @todo How to handle bad unserialize?
+ // @todo Log message
+ return false;
+ }
+
+ $this->_postcreate($_SESSION['imp']['protocol']);
+
+ return true;
+ }
+
+ /**
+ * Create a new Horde_Imap_Client object.
+ *
+ * @param string $username The username to authenticate with.
+ * @param string $password The password to authenticate with.
+ * @param string $key Create a new object using this server key.
+ * @param boolean $global If true, treate the created object as the IMP
+ * global IMAP object.
+ *
+ * @return boolean The object on success, false on error.
+ */
+ public function createImapObject($username, $password, $key,
+ $global = true)
+ {
+ if ($global && !is_null($this->ob)) {
+ return $GLOBALS['imp_imap'];
+ }
+
+ if (($server = $this->loadServerConfig($key)) === false) {
+ return false;
+ }
+
+ $protocol = isset($server['protocol']) ? strtolower($server['protocol']) : 'imap';
+
+ $imap_config = array(
+ 'debug' => isset($server['debug']) ? $server['debug'] : null,
+ 'hostspec' => isset($server['hostspec']) ? $server['hostspec'] : null,
+ 'password' => $password,
+ 'port' => isset($server['port']) ? $server['port'] : null,
+ 'secure' => isset($server['secure']) ? $server['secure'] : false,
+ 'statuscache' => true,
+ 'timeout' => !empty($server['timeout']) ? $server['timeout'] : 10,
+ 'username' => $username,
+ );
+
+ /* Initialize caching. */
+ if (!empty($server['cache'])) {
+ $c = $server['cache'];
+ $driver = $GLOBALS['conf']['cache']['driver'];
+ if ($driver != 'none') {
+ $imap_config['cache'] = array(
+ 'comparator' => empty($c['comparator']) ? false : $c['comparator'],
+ 'compress' => empty($c['compress']) ? false : $c['compress'],
+ 'driver' => $driver,
+ 'driver_params' => Horde::getDriverConfig('cache', $driver),
+ 'id' => empty($c['id']) ? false : $c['id'],
+ 'lang' => empty($c['lang']) ? false : $c['lang'],
+ 'lifetime' => empty($c['lifetime']) ? false : $c['lifetime'],
+ 'slicesize' => empty($c['slicesize']) ? false : $c['slicesize'],
+ );
+ }
+ }
+
+ try {
+ $ob = Horde_Imap_Client::getInstance(($protocol == 'imap') ? 'Socket' : 'Cclient_pop3', $imap_config);
+ } catch (Horde_Imap_Client_Exception $e) {
+ return false;
+ }
+
+ if ($global) {
+ $this->ob = $ob;
+ $this->_postcreate($protocol);
+ }
+
+ return $ob;
+ }
+
+ /**
+ * Alter some IMP settings once we load/create the global object.
+ *
+ * @param string $protocol The protocol used to connect.
+ */
+ protected function _postcreate($protocol)
+ {
+ global $conf, $prefs;
+
+ switch ($protocol) {
+ case 'pop':
+ /* Turn some options off if we are working with POP3. */
+ $conf['user']['allow_folders'] = false;
+ $prefs->setValue('save_sent_mail', false);
+ $prefs->setLocked('save_sent_mail', true);
+ $prefs->setLocked('sent_mail_folder', true);
+ $prefs->setLocked('drafts_folder', true);
+ $prefs->setLocked('trash_folder', true);
+ break;
+ }
+ }
+
+ /**
+ * Is the current IMAP connection read-only?
+ *
+ * @param string $mailbox The mailbox.
+ *
+ * @return boolean Is the connection read-only?
+ */
+ public function isReadOnly($mailbox)
+ {
+ if (!isset($this->_readonly[$mailbox])) {
+ $this->_readonly[$mailbox] =
+ !empty($GLOBALS['conf']['hooks']['mbox_readonly']) &&
+ Horde::callHook('_imp_hook_mbox_readonly', array($mailbox), 'imp');
+ }
+
+ return $this->_readonly[$mailbox];
+ }
+
+ /**
+ * Logs an exception from Horde_Imap_Client.
+ *
+ * @param object Horde_Imap_Client_Exception $e The exception object.
+ */
+ public function logException($e)
+ {
+ Horde::logMessage($e, $e->getFile(), $e->getLine(), PEAR_LOG_ERR);
+ }
+
+ /**
+ * Get the namespace list.
+ *
+ * @return array An array of namespace information.
+ */
+ public function getNamespaceList()
+ {
+ try {
+ return $GLOBALS['imp_imap']->ob->getNamespaces(!empty($_SESSION['imp']['imap_ext']['namespace']) ? $_SESSION['imp']['imap_ext']['namespace'] : array());
+ } catch (Horde_Imap_Client_Exception $e) {
+ // @todo Error handling
+ return array();
+ }
+ }
+
+ /**
+ * Get namespace info for a full folder path.
+ *
+ * @param string $mailbox The folder path. If empty, will return info
+ * on the default namespace (i.e. the first
+ * personal namespace).
+ * @param boolean $empty If true and no matching namespace is found,
+ * return the empty namespace, if it exists.
+ *
+ * @return mixed The namespace info for the folder path or null if the
+ * path doesn't exist.
+ */
+ public function getNamespace($mailbox = null, $empty = true)
+ {
+ if ($_SESSION['imp']['protocol'] == 'pop') {
+ return null;
+ }
+
+ $ns = $this->getNamespaceList();
+
+ if ($mailbox === null) {
+ reset($ns);
+ $mailbox = key($ns);
+ }
+
+ $key = (int)$empty;
+ if (isset($this->_nscache[$key][$mailbox])) {
+ return $this->_nscache[$key][$mailbox];
+ }
+
+ foreach ($ns as $key => $val) {
+ $mbx = $mailbox . $val['delimiter'];
+ if (!empty($key) && (strpos($mbx, $key) === 0)) {
+ $this->_nscache[$key][$mailbox] = $val;
+ return $val;
+ }
+ }
+
+ $this->_nscache[$key][$mailbox] = ($empty && isset($ns[''])) ? $ns[''] : null;
+
+ return $this->_nscache[$key][$mailbox];
+ }
+
+ /**
+ * Get the default personal namespace.
+ *
+ * @return mixed The default personal namespace info.
+ */
+ public function defaultNamespace()
+ {
+ if ($_SESSION['imp']['protocol'] == 'pop') {
+ return null;
+ }
+
+ if (!isset($this->_nsdefault)) {
+ $this->_nsdefault = null;
+ foreach ($this->getNamespaceList() as $val) {
+ if ($val['type'] == 'personal') {
+ $this->_nsdefault = $val;
+ break;
+ }
+ }
+ }
+
+ return $this->_nsdefault;
+ }
+}
--- /dev/null
+<?php
+/**
+ * Contains functions related to managing IMAP Access Control Lists.
+ *
+ * Copyright 2003-2009 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 Chris Hastie <imp@oak-wood.co.uk>
+ * @package IMP
+ */
+class IMP_Imap_Acl
+{
+ /**
+ * Singleton instance.
+ *
+ * @var IMP_Imap_Acl
+ */
+ static protected $_instance = null;
+
+ /**
+ * Hash containing the list of possible rights and a human readable
+ * description of each.
+ *
+ * @var array
+ */
+ protected $_rightsList;
+
+ /**
+ * Array containing user names that cannot have their access rights
+ * changed.
+ *
+ * @var boolean
+ */
+ protected $_protected;
+
+ /**
+ * Attempts to return a reference to a concrete object instance.
+ * It will only create a new instance if no instance currently exists.
+ *
+ * @return IMP_Imap_Acl The created concrete instance.
+ */
+ static public function singleton()
+ {
+ if (!self::$_instance) {
+ self::$_instance = new IMP_Imap_Acl();
+ }
+
+ return self::$_instance;
+ }
+
+ /**
+ * Constructor.
+ */
+ protected function __construct()
+ {
+ if ($_SESSION['imp']['protocol'] != 'imap') {
+ throw new Horde_Exception(_("ACL requires an IMAP server."));
+ }
+
+ $capability = $GLOBALS['imp_imap']->ob->queryCapability('ACL');
+ if (!$capability) {
+ throw new Horde_Exception(_("IMAP server does not support ACLs."));
+ }
+
+ $rfc4314 = $GLOBALS['imp_imap']->ob->queryCapability('RIGHTS');
+
+ $this->_protected = array($GLOBALS['imp_imap']->ob->getParam('username'));
+
+ $this->_rightsList = array(
+ 'l' => array(
+ 'desc' => _("List - user can see the folder"),
+ 'title' => _("List")
+ ),
+ 'r' => array(
+ 'desc' => _("Read messages"),
+ 'title' => _("Read")
+ ),
+ 's' => array(
+ 'desc' => _("Mark with Seen/Unseen flags"),
+ 'title' => _("Mark (Seen)")
+ ),
+ 'w' => array(
+ 'desc' => _("Mark with other flags (e.g. Important/Answered)"),
+ 'title' => _("Mark (Other)")
+ ),
+ 'i' => array(
+ 'desc' => _("Insert messages"),
+ 'title' => _("Insert")
+ ),
+ 'p' => array(
+ 'desc' => _("Post to this folder (not enforced by IMAP)"),
+ 'title' => _("Post")
+ ),
+ 'a' => array(
+ 'desc' => _("Administer - set permissions for other users"),
+ 'title' => _("Administer")
+ )
+ );
+
+ if ($rfc4314) {
+ // RFC 4314 compliant rights
+ $this->_rightsList = array_merge($this->_rightsList, array(
+ 'k' => array(
+ 'desc' => _("Create sub folders"),
+ 'title' => _("Create Folders")
+ ),
+ 'x' => array(
+ 'desc' => _("Delete sub folders"),
+ 'title' => _("Delete Folders")
+ ),
+ 't' => array(
+ 'desc' => _("Delete messages"),
+ 'title' => _("Delete")
+ ),
+ 'e' => array(
+ 'desc' => _("Purge messages"),
+ 'title' => _("Purge")
+ )
+ ));
+ } else {
+ // RFC 2086 compliant rights
+ $this->_rightsList = array_merge($this->_rightsList, array(
+ 'c' => array(
+ 'desc' =>_("Create sub folders"),
+ 'title' => _("Create Folder")
+ ),
+ 'd' => array(
+ 'desc' => _("Delete and purge messages"),
+ 'title' => _("Delete/Purge")
+ )
+ ));
+ }
+ }
+
+ /**
+ * Attempts to retrieve the existing ACL for a mailbox from the server.
+ *
+ * @param string $mbox The mailbox to get the ACL for.
+ *
+ * @return array A hash containing information on the ACL.
+ * @throws Horde_Exception
+ */
+ public function getACL($mbox)
+ {
+ try {
+ return $GLOBALS['imp_imap']->ob->getACL($mbox);
+ } catch (Horde_Imap_Client_Exception $e) {
+ throw new Horde_Exception(_("Could not retrieve ACL"));
+ }
+ }
+
+ /**
+ * Edits an ACL on the server.
+ *
+ * @param string $mbox The mailbox on which to edit the ACL.
+ * @param string $user The user to grant rights to.
+ * @param array $acl The keys of which are the rights to be granted
+ * (see RFC 2086).
+ *
+ * @throws Horde_Exception
+ */
+ public function editACL($mbox, $user, $acl)
+ {
+ try {
+ $GLOBALS['imp_imap']->ob->setACL($mbox, $user, array('rights' => $acl));
+ } catch (Horde_Imap_Client_Exception $e) {
+ throw new Horde_Exception(sprintf(_("Couldn't give user \"%s\" the following rights for the folder \"%s\": %s"), $user, $mbox, implode('', $acl)));
+ }
+ }
+
+ /**
+ * Can a user edit the ACL for this mailbox?
+ *
+ * @param string $mbox The mailbox name.
+ * @param string $user A user name.
+ *
+ * @return boolean True if $user has 'a' right
+ */
+ public function canEdit($mbox, $user)
+ {
+ try {
+ $rights = $GLOBALS['imp_imap']->ob->listACLRights($mbox, $user);
+ foreach ($rights as $val) {
+ if (strpos($val, 'a') !== false) {
+ return true;
+ }
+ }
+ return false;
+ } catch (Horde_Imap_Client_Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * TODO
+ */
+ public function getRights()
+ {
+ return $this->_rightsList;
+ }
+
+ /**
+ * TODO
+ */
+ public function getProtected()
+ {
+ return $this->_protected;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The IMP_Imap_Thread class provides functions to generate thread tree
+ * images.
+ *
+ * Copyright 2005-2009 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_Imap_Thread
+{
+ /**
+ * The thread data object.
+ *
+ * @var Horde_Imap_Client_Thread
+ */
+ protected $_thread;
+
+ /**
+ * Images used and their internal representations.
+ *
+ * @var array
+ */
+ static protected $_imglist = array(
+ '0' => 'blank.png',
+ '1' => 'line.png',
+ '2' => 'join.png',
+ '3' => 'joinbottom-down.png',
+ '4' => 'joinbottom.png'
+ );
+
+ /**
+ * Constructor.
+ *
+ * @param Horde_Imap_Client_Thread $thread The thread data object.
+ */
+ public function __construct($thread)
+ {
+ $this->_thread = $thread;
+ }
+
+ /**
+ * Generate the thread representation for the given index list in the
+ * internal format (a string with each character representing the graphic
+ * to be displayed from $_imglist).
+ *
+ * @param array $indices The list of indices to create a tree for.
+ * @param boolean $sortdir True for newest first, false for oldest first.
+ *
+ * @return array An array with the index as the key and the internal
+ * thread representation as the value.
+ */
+ public function getThreadTreeOb($indices, $sortdir)
+ {
+ $container = $last_level = $last_thread = null;
+ $thread_level = $tree = array();
+ $t = &$this->_thread;
+
+ $indices = array_intersect($t->messageList($sortdir), $indices);
+
+ /* If starting in the middle of a thread, the threadLevel tree needs
+ * to be built from the base of the current thread. */
+ $first = reset($indices);
+ foreach ($t->getThread(reset($indices)) as $val) {
+ if ($first == $val) {
+ break;
+ }
+ $thread_level[$t->getThreadIndent($val)] = $t->lastInLevel($val);
+ }
+
+ foreach ($indices as $val) {
+ $tree[$val] = '';
+
+ $indentBase = $t->getThreadBase($val);
+ if (empty($indentBase)) {
+ continue;
+ }
+
+ $lines = '';
+ $indentLevel = $t->getThreadIndent($val);
+ $lastinlevel = $t->lastInLevel($val);
+
+ if ($lastinlevel && ($indentBase == $val)) {
+ continue;
+ }
+
+ if ($lastinlevel) {
+ $join_img = ($sortdir) ? 3 : 4;
+ } elseif (($indentLevel == 1) && ($indentBase == $val)) {
+ $join_img = ($sortdir) ? 4 : 3;
+ } else {
+ $join_img = 2;
+ }
+
+ $thread_level[$indentLevel] = $lastinlevel;
+ $line = '';
+
+ for ($i = 1; $i < $indentLevel; ++$i) {
+ $line .= (!isset($thread_level[$i]) || ($thread_level[$i])) ? 0 : 1;
+ }
+ $tree[$val] = $line . $join_img;
+ }
+
+ return $tree;
+ }
+
+ /**
+ * Generate the thread representation image for the given index list.
+ *
+ * @param array $indices The list of indices to create a tree for.
+ * @param boolean $sortdir True for newest first, false for oldest first.
+ *
+ * @return array An array with the index as the key and the thread image
+ * representation as the value.
+ */
+ public function getThreadImageTree($indices, $sortdir)
+ {
+ $imgs = $tree = array();
+
+ foreach (self::$_imglist as $key => $val) {
+ $imgs[$key] = Horde::img('tree/' . (($key != 0 && !empty($GLOBALS['nls']['rtl'][$GLOBALS['language']])) ? ('rev-' . $val) : $val), null, null, $GLOBALS['registry']->getImageDir('horde'));
+ }
+
+ foreach ($this->getThreadTreeOb($indices, $sortdir) as $k => $v) {
+ $tree[$k] = '';
+ for ($i = 0, $length = strlen($v); $i < $length; ++$i) {
+ $tree[$k] .= $imgs[$v[$i]];
+ }
+ }
+ return $tree;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The IMP_Imap_Tree class provides a tree view of the mailboxes in an
+ * IMAP/POP3 repository. It provides access functions to iterate through this
+ * tree and query information about individual mailboxes.
+ * In IMP, folders = IMAP mailboxes so the two terms are used interchangably.
+ *
+ * Copyright 2000-2009 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 Chuck Hagenbuch <chuck@horde.org>
+ * @author Jon Parise <jon@horde.org>
+ * @author Anil Madhavapeddy <avsm@horde.org>
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @package IMP
+ */
+class IMP_Imap_Tree
+{
+ /* Constants for mailboxElt attributes. */
+ const ELT_NOSELECT = 1;
+ const ELT_NAMESPACE = 2;
+ const ELT_IS_OPEN = 4;
+ const ELT_IS_SUBSCRIBED = 8;
+ const ELT_NOSHOW = 16;
+ const ELT_IS_POLLED = 32;
+ const ELT_NEED_SORT = 64;
+ const ELT_VFOLDER = 128;
+ const ELT_NONIMAP = 256;
+ const ELT_INVISIBLE = 512;
+
+ /* The isOpen() expanded mode constants. */
+ const OPEN_NONE = 0;
+ const OPEN_ALL = 1;
+ const OPEN_USER = 2;
+
+ /* The manner to which to traverse the tree when calling next(). */
+ const NEXT_SHOWCLOSED = 1;
+ const NEXT_SHOWSUB = 2;
+
+ /* The string used to indicate the base of the tree. */
+ const BASE_ELT = '%';
+
+ /* Defines used with the output from the build() function. */
+ const SPECIAL_INBOX = 1;
+ const SPECIAL_TRASH = 2;
+ const SPECIAL_DRAFT = 3;
+ const SPECIAL_SPAM = 4;
+ const SPECIAL_SENT = 5;
+
+ /* Defines used with folderList(). */
+ const FLIST_CONTAINER = 1;
+ const FLIST_UNSUB = 2;
+ const FLIST_OB = 4;
+ const FLIST_VFOLDER = 8;
+
+ /* Add a percent to folder key since it allows us to sort by name but
+ * never conflict with an IMAP mailbox of the same name (since '%' is an
+ * invalid character in an IMAP mailbox string). */
+ public $VFOLDER_LABEL;
+ public $VFOLDER_KEY;
+
+ /* Defines used with namespace display. */
+ public $SHARED_LABEL;
+ public $SHARED_KEY;
+ public $OTHER_LABEL;
+ public $OTHER_KEY;
+
+ /**
+ * Singleton instance
+ *
+ * @var IMP_Imap_Tree
+ */
+ static protected $_instance = null;
+
+ /**
+ * Array containing the mailbox tree.
+ *
+ * @var array
+ */
+ protected $_tree;
+
+ /**
+ * Location of current element in the tree.
+ *
+ * @var string
+ */
+ protected $_currparent = null;
+
+ /**
+ * Location of current element in the tree.
+ *
+ * @var integer
+ */
+ protected $_currkey = null;
+
+ /**
+ * Location of current element in the tree.
+ *
+ * @var array
+ */
+ protected $_currstack = array();
+
+ /**
+ * Show unsubscribed mailboxes?
+ *
+ * @var boolean
+ */
+ protected $_showunsub = false;
+
+ /**
+ * Parent list.
+ *
+ * @var array
+ */
+ protected $_parent = array();
+
+ /**
+ * The cached list of mailboxes to poll.
+ *
+ * @var array
+ */
+ protected $_poll = null;
+
+ /**
+ * The cached list of expanded folders.
+ *
+ * @var array
+ */
+ protected $_expanded = null;
+
+ /**
+ * Cached list of subscribed mailboxes.
+ *
+ * @var array
+ */
+ protected $_subscribed = null;
+
+ /**
+ * The cached full list of mailboxes on the server.
+ *
+ * @var array
+ */
+ protected $_fulllist = null;
+
+ /**
+ * Tree changed flag. Set when something in the tree has been altered.
+ *
+ * @var boolean
+ */
+ protected $_changed = false;
+
+ /**
+ * Have we shown unsubscribed folders previously?
+ *
+ * @var boolean
+ */
+ protected $_unsubview = false;
+
+ /**
+ * The string used for the IMAP delimiter.
+ *
+ * @var string
+ */
+ protected $_delimiter = '/';
+
+ /**
+ * The list of namespaces to add to the tree.
+ *
+ * @var array
+ */
+ protected $_namespaces = array();
+
+ /**
+ * Used to determine the list of element changes.
+ *
+ * @var array
+ */
+ protected $_eltdiff = null;
+
+ /**
+ * If set, track element changes.
+ *
+ * @var boolean
+ */
+ protected $_trackdiff = true;
+
+ /**
+ * See $open parameter in build().
+ *
+ * @var boolean
+ */
+ protected $_forceopen = false;
+
+ /**
+ * Attempts to return a reference to a concrete IMP_Imap_Tree instance.
+ *
+ * If an IMP_Imap_Tree object is currently stored in the cache, re-create
+ * that object. Else, create a new instance. Ensures that only one
+ * instance is available at any time.
+ *
+ * @return IMP_Imap_Tree The object or null.
+ */
+ static public function singleton()
+ {
+ if (is_null(self::$_instance)) {
+ if (!empty($_SESSION['imp']['cache']['tree'])) {
+ $imp_cache = IMP::getCache();
+ self::$_instance = unserialize($imp_cache->get($_SESSION['imp']['cache']['tree'], 86400));
+ }
+ if (empty(self::$_instance)) {
+ self::$_instance = new IMP_Imap_Tree();
+ }
+ }
+
+ return self::$_instance;
+ }
+
+ /**
+ * Constructor.
+ */
+ protected function __construct()
+ {
+ if ($_SESSION['imp']['protocol'] == 'imap') {
+ $ns = $GLOBALS['imp_imap']->getNamespaceList();
+ $ptr = reset($ns);
+ $this->_delimiter = $ptr['delimiter'];
+ $this->_namespaces = (empty($GLOBALS['conf']['user']['allow_folders'])) ? array() : $ns;
+ }
+
+ if (!isset($_SESSION['imp']['cache']['tree'])) {
+ $imp_cache = IMP::getCache();
+ $_SESSION['imp']['cache']['tree'] = $imp_cache
+ ? uniqid(mt_rand() . Auth::getAuth())
+ : null;
+ }
+
+ /* Must set these values here because PHP 5 does not allow assignment
+ * of const's to gettext strings. */
+ $this->VFOLDER_LABEL = _("Virtual Folders");
+ $this->VFOLDER_KEY = $this->VFOLDER_LABEL . '%';
+ $this->SHARED_LABEL = _("Shared Folders");
+ $this->SHARED_KEY = $this->SHARED_LABEL . '%';
+ $this->OTHER_LABEL = _("Other Users' Folders");
+ $this->OTHER_KEY = $this->OTHER_LABEL . '%';
+
+ $this->init();
+ }
+
+ /**
+ * Do cleanup prior to serialization and provide a list of variables
+ * to serialize.
+ */
+ function __sleep()
+ {
+ /* Don't store $_expanded and $_poll - these values are handled
+ * by the subclasses.
+ * Don't store $_eltdiff - these needs to be regenerated for each
+ * request.
+ * Don't store $_currkey, $_currparent, and $_currstack since the
+ * user MUST call reset() before cycling through the tree.
+ * Don't store $_subscribed and $_fulllist - this information is
+ * stored in the elements.
+ * Reset the $_changed and $_trackdiff flags. */
+ $this->_currkey = $this->_currparent = $this->_eltdiff = $this->_expanded = $this->_fulllist = $this->_poll = $this->_subscribed = null;
+ $this->_currstack = array();
+ $this->_changed = false;
+ $this->_trackdiff = true;
+
+ return array_keys(get_class_vars(__CLASS__));
+ }
+
+ /**
+ * Store a serialized version of ourself in the current session.
+ */
+ function __destruct()
+ {
+ /* We only need to store the object if using Horde_Cache and the tree
+ * has changed. */
+ if (empty($this->_changed) ||
+ is_null($_SESSION['imp']['cache']['tree'])) {
+ return;
+ }
+
+ $imp_cache = IMP::getCache();
+ $imp_cache->set($_SESSION['imp']['cache']['tree'], serialize($this), 86400);
+ }
+
+ /**
+ * Returns the list of mailboxes on the server.
+ *
+ * @param boolean $showunsub Show unsubscribed mailboxes?
+ *
+ * @return array A list of mailbox names.
+ */
+ protected function _getList($showunsub)
+ {
+ if ($showunsub && !is_null($this->_fulllist)) {
+ return $this->_fulllist;
+ } elseif (!$showunsub && !is_null($this->_subscribed)) {
+ return array_keys($this->_subscribed);
+ }
+
+ /* INBOX must always appear. */
+ $names = array('INBOX');
+
+ foreach ($this->_namespaces as $key => $val) {
+ try {
+ $names = array_merge($names, $GLOBALS['imp_imap']->ob->listMailboxes($key . '*', $showunsub ? Horde_Imap_Client::MBOX_ALL : Horde_Imap_Client::MBOX_SUBSCRIBED, array('flat' => true)));
+ if ($showunsub) {
+ $this->_fulllist = $names;
+ } else {
+ $this->_subscribed = $names;
+ }
+ } catch (Horde_Imap_Client_Exception $e) {}
+ }
+
+ return $names;
+ }
+
+ /**
+ * Make a single mailbox tree element.
+ * An element consists of the following items (we use single letters here
+ * to save in session storage space):
+ * 'a' -- Attributes
+ * 'c' -- Level count
+ * 'l' -- Label
+ * 'p' -- Parent node
+ * 'v' -- Value
+ *
+ * @param string $name The mailbox name.
+ * @param integer $attributes The mailbox's attributes.
+ *
+ * @return array See above format.
+ */
+ protected function _makeElt($name, $attributes = 0)
+ {
+ $elt = array(
+ 'a' => $attributes,
+ 'c' => 0,
+ 'p' => self::BASE_ELT,
+ 'v' => $name
+ );
+
+ /* Set subscribed values. We know the folder is subscribed, without
+ * query of the IMAP server, in the following situations:
+ * + Folder is INBOX.
+ * + We are adding while in subscribe-only mode.
+ * + Subscriptions are turned off. */
+ if (!$this->isSubscribed($elt)) {
+ if (!$this->_showunsub ||
+ ($elt['v'] == 'INBOX') ||
+ !$GLOBALS['prefs']->getValue('subscribe')) {
+ $this->_setSubscribed($elt, true);
+ } else {
+ $this->_initSubscribed();
+ $this->_setSubscribed($elt, isset($this->_subscribed[$elt['v']]));
+ }
+ }
+
+ /* Check for polled status. */
+ $this->_initPollList();
+ $this->_setPolled($elt, isset($this->_poll[$elt['v']]));
+
+ /* Check for open status. */
+ switch ($GLOBALS['prefs']->getValue('nav_expanded')) {
+ case self::OPEN_NONE:
+ $open = false;
+ break;
+
+ case self::OPEN_ALL:
+ $open = true;
+ break;
+
+ case self::OPEN_USER:
+ $this->_initExpandedList();
+ $open = !empty($this->_expanded[$elt['v']]);
+ break;
+ }
+ $this->_setOpen($elt, $open);
+
+ /* Computed values. */
+ $ns_info = $this->_getNamespace($elt['v']);
+ $tmp = explode(is_null($ns_info) ? $this->_delimiter : $ns_info['delimiter'], $elt['v']);
+ $elt['c'] = count($tmp) - 1;
+
+ /* Get the mailbox label. */
+ $elt['l'] = IMP::getLabel($tmp[$elt['c']]);
+
+
+ if ($_SESSION['imp']['protocol'] != 'pop') {
+ if (!empty($GLOBALS['conf']['hooks']['display_folder'])) {
+ $this->_setInvisible($elt, !Horde::callHook('_imp_hook_display_folder', array($elt['v']), 'imp'));
+ }
+
+ if ($elt['c'] != 0) {
+ $elt['p'] = implode(is_null($ns_info) ? $this->_delimiter : $ns_info['delimiter'], array_slice($tmp, 0, $elt['c']));
+ }
+
+ if (!is_null($ns_info)) {
+ switch ($ns_info['type']) {
+ case 'personal':
+ /* Strip personal namespace. */
+ if (!empty($ns_info['name']) && ($elt['c'] != 0)) {
+ --$elt['c'];
+ if (strpos($elt['p'], $ns_info['delimiter']) === false) {
+ $elt['p'] = self::BASE_ELT;
+ } elseif (strpos($elt['v'], $ns_info['name'] . 'INBOX' . $ns_info['delimiter']) === 0) {
+ $elt['p'] = 'INBOX';
+ }
+ }
+ break;
+
+ case 'other':
+ case 'shared':
+ if (substr($ns_info['name'], 0, -1 * strlen($ns_info['delimiter'])) == $elt['v']) {
+ $elt['a'] = self::ELT_NOSELECT | self::ELT_NAMESPACE;
+ }
+
+ if ($GLOBALS['prefs']->getValue('tree_view')) {
+ $name = ($ns_info['type'] == 'other') ? $this->OTHER_KEY : $this->SHARED_KEY;
+ if ($elt['c'] == 0) {
+ $elt['p'] = $name;
+ ++$elt['c'];
+ } elseif ($this->_tree[$name] && self::ELT_NOSHOW) {
+ if ($elt['c'] == 1) {
+ $elt['p'] = $name;
+ }
+ } else {
+ ++$elt['c'];
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ return $elt;
+ }
+
+ /**
+ * Initalize the tree.
+ */
+ public function init()
+ {
+ $initmode = (($_SESSION['imp']['protocol'] == 'pop') ||
+ !$GLOBALS['prefs']->getValue('subscribe') ||
+ $_SESSION['imp']['showunsub'])
+ ? 'unsub' : 'sub';
+
+ /* Reset class variables to the defaults. */
+ $this->_changed = true;
+ $this->_currkey = $this->_currparent = $this->_subscribed = null;
+ $this->_currstack = $this->_tree = $this->_parent = array();
+ $this->_showunsub = $this->_unsubview = ($initmode == 'unsub');
+
+ /* Create a placeholder element to the base of the tree list so we can
+ * keep track of whether the base level needs to be sorted. */
+ $this->_tree[self::BASE_ELT] = array(
+ 'a' => self::ELT_NEED_SORT,
+ 'v' => self::BASE_ELT
+ );
+
+ if (empty($GLOBALS['conf']['user']['allow_folders']) ||
+ ($_SESSION['imp']['protocol'] == 'pop')) {
+ $this->_insertElt($this->_makeElt('INBOX', self::ELT_IS_SUBSCRIBED));
+ return;
+ }
+
+ /* Add namespace elements. */
+ foreach ($this->_namespaces as $key => $val) {
+ if ($val['type'] != 'personal' &&
+ $GLOBALS['prefs']->getValue('tree_view')) {
+ $elt = $this->_makeElt(
+ ($val['type'] == 'other') ? $this->OTHER_KEY : $this->SHARED_KEY,
+ self::ELT_NOSELECT | self::ELT_NAMESPACE | self::ELT_NONIMAP | self::ELT_NOSHOW
+ );
+ $elt['l'] = ($val['type'] == 'other')
+ ? $this->OTHER_LABEL : $this->SHARED_LABEL;
+
+ foreach ($this->_namespaces as $val2) {
+ if (($val2['type'] == $val['type']) &&
+ ($val2['name'] != $val['name'])) {
+ $elt['a'] &= ~self::ELT_NOSHOW;
+ break;
+ }
+ }
+
+ $this->_insertElt($elt);
+ }
+ }
+
+ /* Create the list (INBOX and all other hierarchies). */
+ $this->insert($this->_getList($this->_showunsub));
+
+ /* Add virtual folders to the tree. */
+ $this->insertVFolders($GLOBALS['imp_search']->listQueries(true));
+ }
+
+ /**
+ * Expand a mail folder.
+ *
+ * @param string $folder The folder name to expand.
+ * @param boolean $expandall Expand all folders under this one?
+ */
+ public function expand($folder, $expandall = false)
+ {
+ $folder = $this->_convertName($folder);
+
+ if (!isset($this->_tree[$folder])) {
+ return;
+ }
+ $elt = &$this->_tree[$folder];
+
+ if ($this->hasChildren($elt)) {
+ if (!$this->isOpen($elt)) {
+ $this->_changed = true;
+ $this->_setOpen($elt, true);
+ }
+
+ /* Expand all children beneath this one. */
+ if ($expandall && !empty($this->_parent[$folder])) {
+ foreach ($this->_parent[$folder] as $val) {
+ $this->expand($this->_tree[$val]['v'], true);
+ }
+ }
+ }
+ }
+
+ /**
+ * Collapse a mail folder.
+ *
+ * @param string $folder The folder name to collapse.
+ */
+ public function collapse($folder)
+ {
+ $folder = $this->_convertName($folder);
+
+ if (!isset($this->_tree[$folder])) {
+ return;
+ }
+
+ if ($this->isOpen($this->_tree[$folder])) {
+ $this->_changed = true;
+ $this->_setOpen($this->_tree[$folder], false);
+ }
+ }
+
+ /**
+ * Sets the internal array pointer to the next element, and returns the
+ * next object.
+ *
+ * @param integer $mask A mask with the following elements:
+ * <pre>
+ * IMP_Imap_Tree::NEXT_SHOWCLOSED - Don't ignore closed elements.
+ * IMP_Imap_Tree::NEXT_SHOWSUB - Only show subscribed elements.
+ * </pre>
+ *
+ * @return mixed Returns the next element or false if the element doesn't
+ * exist.
+ */
+ public function next($mask = 0)
+ {
+ if (is_null($this->_currkey) && is_null($this->_currparent)) {
+ return false;
+ }
+
+ $curr = $this->current();
+
+ $old_showunsub = $this->_showunsub;
+ if ($mask & self::NEXT_SHOWSUB) {
+ $this->_showunsub = false;
+ }
+
+ if ($this->_activeElt($curr) &&
+ (($mask & self::NEXT_SHOWCLOSED) || $this->isOpen($curr)) &&
+ ($this->_currparent != $curr['v'])) {
+ /* If the current element is open, and children exist, move into
+ * it. */
+ $this->_currstack[] = array('k' => $this->_currkey, 'p' => $this->_currparent);
+ $this->_currkey = 0;
+ $this->_currparent = $curr['v'];
+ $this->_sortLevel($curr['v']);
+
+ $curr = $this->current();
+ if ($GLOBALS['prefs']->getValue('tree_view') &&
+ $this->isNamespace($curr) &&
+ !$this->_isNonIMAPElt($curr) &&
+ ($this->_tree[$curr['p']] && self::ELT_NOSHOW)) {
+ $this->next($mask);
+ }
+ } else {
+ /* Else, increment within the current subfolder. */
+ $this->_currkey++;
+ }
+
+ $curr = $this->current();
+ if (!$curr) {
+ if (empty($this->_currstack)) {
+ $this->_currkey = $this->_currparent = null;
+ $this->_showunsub = $old_showunsub;
+ return false;
+ } else {
+ do {
+ $old = array_pop($this->_currstack);
+ $this->_currkey = $old['k'] + 1;
+ $this->_currparent = $old['p'];
+ } while ((($curr = $this->current()) == false) &&
+ count($this->_currstack));
+ }
+ }
+
+ $res = $this->_activeElt($curr);
+ $this->_showunsub = $old_showunsub;
+ return ($res) ? $curr : $this->next($mask);
+ }
+
+ /**
+ * Set internal pointer to the head of the tree.
+ * This MUST be called before you can traverse the tree with next().
+ *
+ * @return mixed Returns the element at the head of the tree or false
+ * if the element doesn't exist.
+ */
+ public function reset()
+ {
+ $this->_currkey = 0;
+ $this->_currparent = self::BASE_ELT;
+ $this->_currstack = array();
+ $this->_sortLevel($this->_currparent);
+ return $this->current();
+ }
+
+ /**
+ * Return the current tree element.
+ *
+ * @return array The current tree element or false if there is no
+ * element.
+ */
+ public function current()
+ {
+ return (!isset($this->_parent[$this->_currparent][$this->_currkey]))
+ ? false
+ : $this->_tree[$this->_parent[$this->_currparent][$this->_currkey]];
+ }
+
+ /**
+ * Determines if there are more elements in the current tree level.
+ *
+ * @return boolean True if there are more elements, false if this is the
+ * last element.
+ */
+ public function peek()
+ {
+ for ($i = ($this->_currkey + 1); ; ++$i) {
+ if (!isset($this->_parent[$this->_currparent][$i])) {
+ return false;
+ }
+ if ($this->_activeElt($this->_tree[$this->_parent[$this->_currparent][$i]])) {
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Returns the requested element.
+ *
+ * @param string $name The name of the tree element.
+ *
+ * @return array Returns the requested element or false if not found.
+ */
+ public function get($name)
+ {
+ $name = $this->_convertName($name);
+ return (isset($this->_tree[$name])) ? $this->_tree[$name] : false;
+ }
+
+ /**
+ * Insert a folder/mailbox into the tree.
+ *
+ * @param mixed $id The name of the folder (or a list of folder names)
+ * to add.
+ */
+ public function insert($id)
+ {
+ if (is_array($id)) {
+ /* We want to add from the BASE of the tree up for efficiency
+ * sake. */
+ $this->_sortList($id);
+ } else {
+ $id = array($id);
+ }
+
+ foreach ($id as $val) {
+ if (isset($this->_tree[$val]) &&
+ !$this->isContainer($this->_tree[$val])) {
+ continue;
+ }
+
+ $ns_info = $this->_getNamespace($val);
+ if (is_null($ns_info)) {
+ if (strpos($val, $this->VFOLDER_KEY . $this->_delimiter) === 0) {
+ $elt = $this->_makeElt($this->VFOLDER_KEY, self::ELT_VFOLDER | self::ELT_NOSELECT | self::ELT_NONIMAP);
+ $elt['l'] = $this->VFOLDER_LABEL;
+ $this->_insertElt($elt);
+ }
+
+ $elt = $this->_makeElt($val, self::ELT_VFOLDER | self::ELT_IS_SUBSCRIBED);
+ $elt['l'] = $elt['v'] = String::substr($val, String::length($this->VFOLDER_KEY) + String::length($this->_delimiter));
+ $this->_insertElt($elt);
+ } else {
+ /* Break apart the name via the delimiter and go step by
+ * step through the name to make sure all subfolders exist
+ * in the tree. */
+ $parts = explode($ns_info['delimiter'], $val);
+ $parts[0] = $this->_convertName($parts[0]);
+ $parts_count = count($parts);
+ for ($i = 0; $i < $parts_count; ++$i) {
+ $part = implode($ns_info['delimiter'], array_slice($parts, 0, $i + 1));
+
+ if (isset($this->_tree[$part])) {
+ if (($part == $val) &&
+ $this->isContainer($this->_tree[$part])) {
+ $this->_setContainer($this->_tree[$part], false);
+ }
+ } else {
+ $this->_insertElt(($part == $val) ? $this->_makeElt($part) : $this->_makeElt($part, self::ELT_NOSELECT));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Insert an element into the tree.
+ *
+ * @param array $elt The element to insert. The key in the tree is the
+ * 'v' (value) element of the element.
+ */
+ protected function _insertElt($elt)
+ {
+ if (!strlen($elt['l']) || isset($this->_tree[$elt['v']])) {
+ return;
+ }
+
+ // UW fix - it may return both 'foo' and 'foo/' as folder names.
+ // Only add one of these (without the namespace character) to
+ // the tree. See Ticket #5764.
+ $ns_info = $this->_getNamespace($elt['v']);
+ if (isset($this->_tree[rtrim($elt['v'], is_null($ns_info) ? $this->_delimiter : $ns_info['delimiter'])])) {
+ return;
+ }
+
+ $this->_changed = true;
+
+ /* Set the parent array to the value in $elt['p']. */
+ if (empty($this->_parent[$elt['p']])) {
+ $this->_parent[$elt['p']] = array();
+ // This is a case where it is possible that the parent element has
+ // changed (it now has children) but we can't catch it via the
+ // bitflag (since hasChildren() is dynamically determined).
+ if ($this->_trackdiff && !is_null($this->_eltdiff)) {
+ $this->_eltdiff['c'][$elt['p']] = 1;
+ }
+ }
+ $this->_parent[$elt['p']][] = $elt['v'];
+ $this->_tree[$elt['v']] = $elt;
+
+ if ($this->_trackdiff && !is_null($this->_eltdiff)) {
+ $this->_eltdiff['a'][$elt['v']] = 1;
+ }
+
+ /* Make sure we are sorted correctly. */
+ if (count($this->_parent[$elt['p']]) > 1) {
+ $this->_setNeedSort($this->_tree[$elt['p']], true);
+ }
+ }
+
+ /**
+ * Delete an element from the tree.
+ *
+ * @param mixed $id The element name or an array of element names.
+ *
+ * @return boolean Return true on success, false on error.
+ */
+ public function delete($id)
+ {
+ if (is_array($id)) {
+ /* We want to delete from the TOP of the tree down to ensure that
+ * parents have an accurate view of what children are left. */
+ $this->_sortList($id);
+ $id = array_reverse($id);
+
+ $success = true;
+ foreach ($id as $val) {
+ $currsuccess = $this->delete($val);
+ if (!$currsuccess) {
+ $success = false;
+ }
+ }
+ return $success;
+ } else {
+ $id = $this->_convertName($id, true);
+ }
+
+ $vfolder_base = ($id == $this->VFOLDER_LABEL);
+ $search_id = $GLOBALS['imp_search']->createSearchID($id);
+
+ if ($vfolder_base ||
+ (isset($this->_tree[$search_id]) &&
+ $this->isVFolder($this->_tree[$search_id]))) {
+ if (!$vfolder_base) {
+ $id = $search_id;
+
+ }
+ $parent = $this->_tree[$id]['p'];
+ unset($this->_tree[$id]);
+
+ /* Delete the entry from the parent tree. */
+ $key = array_search($id, $this->_parent[$parent]);
+ unset($this->_parent[$parent][$key]);
+
+ /* Rebuild the parent tree. */
+ if (!$vfolder_base && empty($this->_parent[$parent])) {
+ $this->delete($parent);
+ } else {
+ $this->_parent[$parent] = array_values($this->_parent[$parent]);
+ }
+ $this->_changed = true;
+
+ return true;
+ }
+
+ $ns_info = $this->_getNamespace($id);
+
+ if (($id == 'INBOX') ||
+ !isset($this->_tree[$id]) ||
+ ($id == $ns_info['name'])) {
+ return false;
+ }
+
+ $this->_changed = true;
+
+ $elt = &$this->_tree[$id];
+
+ /* Do not delete from tree if there are child elements - instead,
+ * convert to a container element. */
+ if ($this->hasChildren($elt)) {
+ $this->_setContainer($elt, true);
+ return true;
+ }
+
+ $parent = $elt['p'];
+
+ /* Delete the tree entry. */
+ unset($this->_tree[$id]);
+
+ /* Delete the entry from the parent tree. */
+ $key = array_search($id, $this->_parent[$parent]);
+ unset($this->_parent[$parent][$key]);
+
+ if (!is_null($this->_eltdiff)) {
+ $this->_eltdiff['d'][$id] = 1;
+ }
+
+ if (empty($this->_parent[$parent])) {
+ /* This folder is now completely empty (no children). If the
+ * folder is a container only, we should delete the folder from
+ * the tree. */
+ unset($this->_parent[$parent]);
+ if (isset($this->_tree[$parent])) {
+ if ($this->isContainer($this->_tree[$parent]) &&
+ !$this->isNamespace($this->_tree[$parent])) {
+ $this->delete($parent);
+ } else {
+ $this->_modifyExpandedList($parent, 'remove');
+ $this->_setOpen($this->_tree[$parent], false);
+ /* This is a case where it is possible that the parent
+ * element has changed (it no longer has children) but
+ * we can't catch it via the bitflag (since hasChildren()
+ * is dynamically determined). */
+ if (!is_null($this->_eltdiff)) {
+ $this->_eltdiff['c'][$parent] = 1;
+ }
+ }
+ }
+ } else {
+ /* Rebuild the parent tree. */
+ $this->_parent[$parent] = array_values($this->_parent[$parent]);
+ }
+
+ /* Remove the mailbox from the expanded folders list. */
+ $this->_modifyExpandedList($id, 'remove');
+
+ /* Remove the mailbox from the nav_poll list. */
+ $this->removePollList($id);
+
+ return true;
+ }
+
+ /**
+ * Subscribe an element to the tree.
+ *
+ * @param mixed $id The element name or an array of element names.
+ */
+ public function subscribe($id)
+ {
+ if (!is_array($id)) {
+ $id = array($id);
+ }
+
+ foreach ($id as $val) {
+ $val = $this->_convertName($val);
+ if (isset($this->_tree[$val])) {
+ $this->_changed = true;
+ $this->_setSubscribed($this->_tree[$val], true);
+ $this->_setContainer($this->_tree[$val], false);
+ }
+ }
+ }
+
+ /**
+ * Unsubscribe an element from the tree.
+ *
+ * @param mixed $id The element name or an array of element names.
+ */
+ public function unsubscribe($id)
+ {
+ if (!is_array($id)) {
+ $id = array($id);
+ } else {
+ /* We want to delete from the TOP of the tree down to ensure that
+ * parents have an accurate view of what children are left. */
+ $this->_sortList($id);
+ $id = array_reverse($id);
+ }
+
+ foreach ($id as $val) {
+ $val = $this->_convertName($val);
+
+ /* INBOX can never be unsubscribed to. */
+ if (isset($this->_tree[$val]) && ($val != 'INBOX')) {
+ $this->_changed = $this->_unsubview = true;
+
+ $elt = &$this->_tree[$val];
+
+ /* Do not delete from tree if there are child elements -
+ * instead, convert to a container element. */
+ if (!$this->_showunsub && $this->hasChildren($elt)) {
+ $this->_setContainer($elt, true);
+ }
+
+ /* Set as unsubscribed, add to unsubscribed list, and remove
+ * from subscribed list. */
+ $this->_setSubscribed($elt, false);
+ }
+ }
+ }
+
+ /**
+ * Set an attribute for an element.
+ *
+ * @param array &$elt The tree element.
+ * @param integer $const The constant to set/remove from the bitmask.
+ * @param boolean $bool Should the attribute be set?
+ */
+ protected function _setAttribute(&$elt, $const, $bool)
+ {
+ if ($bool) {
+ $elt['a'] |= $const;
+ } else {
+ $elt['a'] &= ~$const;
+ }
+ }
+
+ /**
+ * Does the element have any active children?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return boolean True if the element has active children.
+ */
+ public function hasChildren($elt)
+ {
+ if (isset($this->_parent[$elt['v']])) {
+ if ($this->_showunsub) {
+ return true;
+ }
+
+ foreach ($this->_parent[$elt['v']] as $val) {
+ $child = &$this->_tree[$val];
+ if ($this->isSubscribed($child) ||
+ $this->hasChildren($this->_tree[$val])) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Is the tree element open?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the element is open.
+ */
+ public function isOpen($elt)
+ {
+ return (($elt['a'] & self::ELT_IS_OPEN) && $this->hasChildren($elt));
+ }
+
+ /**
+ * Set the open attribute for an element.
+ *
+ * @param array &$elt A tree element.
+ * @param boolean $bool The setting.
+ */
+ protected function _setOpen(&$elt, $bool)
+ {
+ $this->_setAttribute($elt, self::ELT_IS_OPEN, $bool);
+ $this->_modifyExpandedList($elt['v'], $bool ? 'add' : 'remove');
+ }
+
+ /**
+ * Is this element a container only, not a mailbox (meaning you can
+ * not open it)?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the element is a container.
+ */
+ public function isContainer($elt)
+ {
+ return (($elt['a'] & self::ELT_NOSELECT) ||
+ (!$this->_showunsub &&
+ !$this->isSubscribed($elt) &&
+ $this->hasChildren($elt)));
+ }
+
+ /**
+ * Set the element as a container?
+ *
+ * @param array &$elt A tree element.
+ * @param boolean $bool Is the element a container?
+ */
+ protected function _setContainer(&$elt, $bool)
+ {
+ $this->_setAttribute($elt, self::ELT_NOSELECT, $bool);
+ }
+
+ /**
+ * Is the user subscribed to this element?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the user is subscribed to the element.
+ */
+ public function isSubscribed($elt)
+ {
+ return $elt['a'] & self::ELT_IS_SUBSCRIBED;
+ }
+
+ /**
+ * Set the subscription status for an element.
+ *
+ * @param array &$elt A tree element.
+ * @param boolean $bool Is the element subscribed to?
+ */
+ protected function _setSubscribed(&$elt, $bool)
+ {
+ $this->_setAttribute($elt, self::ELT_IS_SUBSCRIBED, $bool);
+ if (!is_null($this->_subscribed)) {
+ if ($bool) {
+ $this->_subscribed[$elt['v']] = 1;
+ } else {
+ unset($this->_subscribed[$elt['v']]);
+ }
+ }
+ }
+
+ /**
+ * Is the element a namespace container?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the element is a namespace container.
+ */
+ public function isNamespace($elt)
+ {
+ return $elt['a'] & self::ELT_NAMESPACE;
+ }
+
+ /**
+ * Is the element a non-IMAP element?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the element is a non-IMAP element.
+ */
+ protected function _isNonIMAPElt($elt)
+ {
+ return $elt['a'] & self::ELT_NONIMAP;
+ }
+
+ /**
+ * Initialize the expanded folder list.
+ */
+ protected function _initExpandedList()
+ {
+ if (is_null($this->_expanded)) {
+ $serialized = $GLOBALS['prefs']->getValue('expanded_folders');
+ $this->_expanded = ($serialized) ? unserialize($serialized) : array();
+ }
+ }
+
+ /**
+ * Add/remove an element to the expanded list.
+ *
+ * @param string $id The element name to add/remove.
+ * @param string $action Either 'add' or 'remove';
+ */
+ protected function _modifyExpandedList($id, $action)
+ {
+ $this->_initExpandedList();
+ if ($action == 'add') {
+ $this->_expanded[$id] = true;
+ } else {
+ unset($this->_expanded[$id]);
+ }
+ $GLOBALS['prefs']->setValue('expanded_folders', serialize($this->_expanded));
+ }
+
+ /**
+ * Initializes and returns the list of mailboxes to poll.
+ *
+ * @param boolean $prune Prune non-existant folders from list?
+ * @param boolean $sort Sort the directory list?
+ *
+ * @return array The list of mailboxes to poll.
+ */
+ public function getPollList($prune = false, $sort = false)
+ {
+ $this->_initPollList();
+
+ $plist = ($prune) ? array_values(array_intersect(array_keys($this->_poll), $this->folderList())) : $this->_poll;
+ if ($sort) {
+ $ns_new = $this->_getNamespace(null);
+ Horde_Imap_Client_Sort::sortMailboxes($plist, array('delimiter' => $ns_new['delimiter'], 'inbox' => true));
+ }
+
+ return $plist;
+ }
+
+ /**
+ * Init the poll list. Called once per session.
+ */
+ protected function _initPollList()
+ {
+ if (is_null($this->_poll)) {
+ /* We ALWAYS poll the INBOX. */
+ $this->_poll = array('INBOX' => 1);
+
+ /* Add the list of polled mailboxes from the prefs. */
+ if ($GLOBALS['prefs']->getValue('nav_poll_all')) {
+ $navPollList = array_flip($this->_getList(true));
+ } else {
+ $old_error = error_reporting(0);
+ $navPollList = unserialize($GLOBALS['prefs']->getValue('nav_poll'));
+ error_reporting($old_error);
+ }
+ if ($navPollList) {
+ $this->_poll += $navPollList;
+ }
+ }
+ }
+
+ /**
+ * Add element to the poll list.
+ *
+ * @param mixed $id The element name or a list of element names to add.
+ */
+ public function addPollList($id)
+ {
+ if (!is_array($id)) {
+ $id = array($id);
+ }
+
+ if (!empty($id) && !$GLOBALS['prefs']->isLocked('nav_poll')) {
+ $imp_folder = IMP_Folder::singleton();
+ $this->getPollList();
+ foreach ($id as $val) {
+ if (!$this->isSubscribed($this->_tree[$val])) {
+ $imp_folder->subscribe(array($val));
+ }
+ $this->_poll[$val] = true;
+ $this->_setPolled($this->_tree[$val], true);
+ }
+ $GLOBALS['prefs']->setValue('nav_poll', serialize($this->_poll));
+ $this->_changed = true;
+ }
+ }
+
+ /**
+ * Remove element from the poll list.
+ *
+ * @param string $id The folder/mailbox or a list of folders/mailboxes
+ * to remove.
+ */
+ public function removePollList($id)
+ {
+ if (!is_array($id)) {
+ $id = array($id);
+ }
+
+ $removed = false;
+
+ if (!$GLOBALS['prefs']->isLocked('nav_poll')) {
+ $this->getPollList();
+ foreach ($id as $val) {
+ if ($val != 'INBOX') {
+ unset($this->_poll[$val]);
+ if (isset($this->_tree[$val])) {
+ $this->_setPolled($this->_tree[$val], false);
+ }
+ $removed = true;
+ }
+ }
+ if ($removed) {
+ $GLOBALS['prefs']->setValue('nav_poll', serialize($this->_poll));
+ $this->_changed = true;
+ }
+ }
+ }
+
+ /**
+ * Does the user want to poll this mailbox for new/unseen messages?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the user wants to poll the element.
+ */
+ public function isPolled($elt)
+ {
+ return ($GLOBALS['prefs']->getValue('nav_poll_all')) ? true : ($elt['a'] & self::ELT_IS_POLLED);
+ }
+
+ /**
+ * Set the polled attribute for an element.
+ *
+ * @param array &$elt A tree element.
+ * @param boolean $bool The setting.
+ */
+ protected function _setPolled(&$elt, $bool)
+ {
+ $this->_setAttribute($elt, self::ELT_IS_POLLED, $bool);
+ }
+
+ /**
+ * Is the element invisible?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the element is marked as invisible.
+ */
+ public function isInvisible($elt)
+ {
+ return $elt['a'] & self::ELT_INVISIBLE;
+ }
+
+ /**
+ * Set the invisible attribute for an element.
+ *
+ * @param array &$elt A tree element.
+ * @param boolean $bool The setting.
+ */
+ protected function _setInvisible(&$elt, $bool)
+ {
+ $this->_setAttribute($elt, self::ELT_INVISIBLE, $bool);
+ }
+
+ /**
+ * Flag the element as needing its children to be sorted.
+ *
+ * @param array &$elt A tree element.
+ * @param boolean $bool The setting.
+ */
+ protected function _setNeedSort(&$elt, $bool)
+ {
+ $this->_setAttribute($elt, self::ELT_NEED_SORT, $bool);
+ }
+
+ /**
+ * Does this element's children need sorting?
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the children need to be sorted.
+ */
+ protected function _needSort($elt)
+ {
+ return (($elt['a'] & self::ELT_NEED_SORT) && (count($this->_parent[$elt['v']]) > 1));
+ }
+
+ /**
+ * Initialize the list of subscribed mailboxes.
+ */
+ protected function _initSubscribed()
+ {
+ if (is_null($this->_subscribed)) {
+ $this->_getList(false);
+ }
+ }
+
+ /**
+ * Should we expand all elements?
+ */
+ public function expandAll()
+ {
+ foreach ($this->_parent[self::BASE_ELT] as $val) {
+ $this->expand($val, true);
+ }
+ }
+
+ /**
+ * Should we collapse all elements?
+ */
+ public function collapseAll()
+ {
+ foreach ($this->_tree as $key => $val) {
+ if ($key !== self::BASE_ELT) {
+ $this->collapse($val['v']);
+ }
+ }
+ }
+
+ /**
+ * Switch subscribed/unsubscribed viewing.
+ *
+ * @param boolean $unsub Show unsubscribed elements?
+ */
+ public function showUnsubscribed($unsub)
+ {
+ if ((bool)$unsub === $this->_showunsub) {
+ return;
+ }
+
+ $this->_showunsub = $unsub;
+ $this->_changed = true;
+
+ /* If we are switching from unsubscribed to subscribed, no need
+ * to do anything (we just ignore unsubscribed stuff). */
+ if ($unsub === false) {
+ return;
+ }
+
+ /* If we are switching from subscribed to unsubscribed, we need
+ * to add all unsubscribed elements that live in currently
+ * discovered items. */
+ $this->_unsubview = true;
+ $this->_trackdiff = false;
+ $this->insert($this->_getList(true));
+ $this->_trackdiff = true;
+ }
+
+ /**
+ * Get information about new/unseen/total messages for the given element.
+ *
+ * @param string $name The element name (UTF7-IMAP).
+ *
+ * @return array Array with the following fields:
+ * <pre>
+ * 'messages' - (integer) Number of total messages.
+ * 'recent' - (integer) Number of new messages.
+ * 'unseen' - (integer) Number of unseen messages.
+ * </pre>
+ */
+ public function getElementInfo($name)
+ {
+ try {
+ return $GLOBALS['imp_imap']->ob->status($name, Horde_Imap_Client::STATUS_MESSAGES | Horde_Imap_Client::STATUS_RECENT | Horde_Imap_Client::STATUS_UNSEEN);
+ } catch (Horde_Imap_Client_Exception $e) {
+ return array();
+ }
+ }
+
+ /**
+ * Sorts a list of mailboxes.
+ *
+ * @param array &$mbox The list of mailboxes to sort.
+ * @param boolean $base Are we sorting a list of mailboxes in the base
+ * of the tree.
+ */
+ protected function _sortList(&$mbox, $base = false)
+ {
+ $config_array = array(
+ 'delimiter' => $this->_delimiter,
+ 'inbox' => true
+ );
+
+ if ($base) {
+ $basesort = array();
+ foreach ($mbox as $val) {
+ $basesort[$val] = ($val == 'INBOX') ? 'INBOX' : $this->_tree[$val]['l'];
+ }
+ $config_array['index'] = true;
+ Horde_Imap_Client_Sort::sortMailboxes($basesort, $config_array);
+ $mbox = array_keys($basesort);
+ } else {
+ Horde_Imap_Client_Sort::sortMailboxes($mbox, $config_array);
+ }
+
+ if ($base) {
+ for ($i = 0, $count = count($mbox); $i < $count; ++$i) {
+ if ($this->_isNonIMAPElt($this->_tree[$mbox[$i]])) {
+ /* Already sorted by name - simply move to the end of
+ * the array. */
+ $mbox[] = $mbox[$i];
+ unset($mbox[$i]);
+ }
+ }
+ $mbox = array_values($mbox);
+ }
+ }
+
+ /**
+ * Is the given element an "active" element (i.e. an element that should
+ * be worked with given the current viewing parameters).
+ *
+ * @param array $elt A tree element.
+ *
+ * @return boolean True if it is an active element.
+ */
+ protected function _activeElt($elt)
+ {
+ return (!$this->isInvisible($elt) &&
+ ($this->_showunsub ||
+ ($this->isSubscribed($elt) && !$this->isContainer($elt)) ||
+ $this->hasChildren($elt)));
+ }
+
+ /**
+ * Convert a mailbox name to the correct, internal name (i.e. make sure
+ * INBOX is always capitalized for IMAP servers).
+ *
+ * @param string $name The mailbox name.
+ *
+ * @return string The converted name.
+ */
+ protected function _convertName($name)
+ {
+ return (strcasecmp($name, 'INBOX') == 0) ? 'INBOX' : $name;
+ }
+
+ /**
+ * Get namespace info for a full folder path.
+ *
+ * @param string $mailbox The folder path.
+ *
+ * @return mixed The namespace info for the folder path or null if the
+ * path doesn't exist.
+ */
+ protected function _getNamespace($mailbox)
+ {
+ if (!in_array($mailbox, array($this->OTHER_KEY, $this->SHARED_KEY, $this->VFOLDER_KEY)) &&
+ (strpos($mailbox, $this->VFOLDER_KEY . $this->_delimiter) !== 0)) {
+ return $GLOBALS['imp_imap']->getNamespace($mailbox);
+ }
+ return null;
+ }
+
+ /**
+ * Set the start point for determining element differences via eltDiff().
+ */
+ public function eltDiffStart()
+ {
+ $this->_eltdiff = array('a' => array(), 'c' => array(), 'd' => array());
+ }
+
+ /**
+ * Return the list of elements that have changed since eltDiffStart()
+ * was last called.
+ *
+ * @return array Returns false if no changes have occurred, or an array
+ * with the following keys:
+ * <pre>
+ * 'a' => A list of elements that have been added.
+ * 'c' => A list of elements that have been changed.
+ * 'd' => A list of elements that have been deleted.
+ * </pre>
+ */
+ public function eltDiff()
+ {
+ if (is_null($this->_eltdiff) || !$this->_changed) {
+ return false;
+ }
+
+ $ret = array(
+ 'a' => array_keys($this->_eltdiff['a']),
+ 'c' => array_keys($this->_eltdiff['c']),
+ 'd' => array_keys($this->_eltdiff['d'])
+ );
+
+ $this->_eltdiff = null;
+
+ return $ret;
+ }
+
+ /**
+ * Inserts virtual folders into the tree.
+ *
+ * @param array $id_list An array with the folder IDs to add as the key
+ * and the labels as the value.
+ */
+ public function insertVFolders($id_list)
+ {
+ if (empty($id_list) ||
+ empty($GLOBALS['conf']['user']['allow_folders'])) {
+ return;
+ }
+
+ $adds = $id = array();
+
+ foreach ($id_list as $key => $val) {
+ $id[$GLOBALS['imp_search']->createSearchID($key)] = $val;
+ }
+
+ foreach (array_keys($id) as $key) {
+ $id_key = $this->VFOLDER_KEY . $this->_delimiter . $key;
+ if (!isset($this->_tree[$id_key])) {
+ $adds[] = $id_key;
+ }
+ }
+
+ if (empty($adds)) {
+ return;
+ }
+
+ $this->insert($adds);
+
+ foreach ($id as $key => $val) {
+ $this->_tree[$key]['l'] = $val;
+ }
+
+ /* Sort the Virtual Folder list in the object, if necessary. */
+ if ($this->_needSort($this->_tree[$this->VFOLDER_KEY])) {
+ $vsort = array();
+ foreach ($this->_parent[$this->VFOLDER_KEY] as $val) {
+ $vsort[$val] = $this->_tree[$val]['l'];
+ }
+ natcasesort($vsort);
+ $this->_parent[$this->VFOLDER_KEY] = array_keys($vsort);
+ $this->_setNeedSort($this->_tree[$this->VFOLDER_KEY], false);
+ $this->_changed = true;
+ }
+ }
+
+ /**
+ * Builds a list of folders, suitable to render a folder tree.
+ *
+ * @param integer $mask The mask to pass to next().
+ * @param boolean $open If using the base folder icons, display a
+ * different icon whether the folder is opened or
+ * closed.
+ *
+ * @return array An array with three elements: the folder list, the total
+ * number of new messages, and a list with folder names
+ * suitable for user interaction.
+ * The folder list array contains the following added
+ * entries on top of the entries provided by element():
+ * <pre>
+ * 'display' - The mailbox name run through IMP::displayFolder().
+ * 'peek' - See peek().
+ * </pre>
+ */
+ public function build($mask = 0, $open = true)
+ {
+ $displayNames = $newmsgs = $rows = array();
+ $this->_forceopen = $open;
+
+ /* Start iterating through the list of mailboxes, displaying them. */
+ $mailbox = $this->reset();
+ do {
+ $row = $this->element($mailbox['v']);
+
+ $row['display'] = ($this->_isNonIMAPElt($mailbox)) ? $mailbox['l'] : IMP::displayFolder($mailbox['v']);
+ $row['peek'] = $this->peek();
+
+ if (!empty($row['recent'])) {
+ $newmsgs[$row['value']] = $row['recent'];
+ }
+
+ /* Hide folder prefixes from the user. */
+ if ($row['level'] >= 0) {
+ $rows[] = $row;
+ $displayNames[] = addslashes($row['display']);
+ }
+ } while (($mailbox = $this->next($mask)));
+
+ $this->_forceopen = false;
+
+ return array($rows, $newmsgs, $displayNames);
+ }
+
+ /**
+ * Get any custom icon configured for the given element.
+ *
+ * @params array $elt A tree element.
+ *
+ * @return array An array with the 'icon', 'icondir', and 'alt'
+ * information for the element, or false if no icon
+ * available.
+ */
+ public function getCustomIcon($elt)
+ {
+ static $mbox_icons;
+
+ if (isset($mbox_icons) && !$mbox_icons) {
+ return false;
+ }
+
+ /* Call the mailbox icon hook, if requested. */
+ if (empty($GLOBALS['conf']['hooks']['mbox_icon'])) {
+ $mbox_icons = false;
+ return false;
+ }
+
+ if (!isset($mbox_icons)) {
+ $mbox_icons = Horde::callHook('_imp_hook_mbox_icons', array(), 'imp', false);
+ if (!$mbox_icons) {
+ return false;
+ }
+ }
+
+ if (isset($mbox_icons[$elt['v']])) {
+ return array('icon' => $mbox_icons[$elt['v']]['icon'], 'icondir' => $mbox_icons[$elt['v']]['icondir'], 'alt' => $mbox_icons[$elt['v']]['alt']);
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns whether this element is a virtual folder.
+ *
+ * @param array $elt A tree element.
+ *
+ * @return integer True if the element is a virtual folder.
+ */
+ public function isVFolder($elt)
+ {
+ return $elt['a'] & self::ELT_VFOLDER;
+ }
+
+ /**
+ * Rename a current folder.
+ *
+ * @param array $old The old folder names.
+ * @param array $new The new folder names.
+ */
+ public function rename($old, $new)
+ {
+ foreach ($old as $key => $val) {
+ $polled = (isset($this->_tree[$val])) ? $this->isPolled($this->_tree[$val]) : false;
+ if ($this->delete($val)) {
+ $this->insert($new[$key]);
+ if ($polled) {
+ $this->addPollList($new[$key]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a list of all IMAP mailboxes in the tree.
+ *
+ * @param integer $mask A mask with the following elements:
+ * <pre>
+ * IMP_Imap_Tree::FLIST_CONTAINER - Show container elements.
+ * IMP_Imap_Tree::FLIST_UNSUB - Show unsubscribed elements.
+ * IMP_Imap_Tree::FLIST_OB - Return full tree object.
+ * IMP_Imap_Tree::FLIST_VFOLDER - Show Virtual Folders.
+ * </pre>
+ * @param string $base Return all mailboxes below this element.
+ *
+ * @return array An array of IMAP mailbox names.
+ */
+ public function folderList($mask = 0, $base = null)
+ {
+ $baseindex = null;
+ $ret_array = array();
+
+ $diff_unsub = (($mask & self::FLIST_UNSUB) != $this->_showunsub) ? $this->_showunsub : null;
+ $this->showUnsubscribed($mask & self::FLIST_UNSUB);
+
+ $mailbox = $this->reset();
+
+ // Search to base element.
+ if (!is_null($base)) {
+ while ($mailbox && $mailbox['v'] != $base) {
+ $mailbox = $this->next(self::NEXT_SHOWCLOSED);
+ }
+ if ($mailbox) {
+ $baseindex = count($this->_currstack);
+ $baseparent = $this->_currparent;
+ $basekey = $this->_currkey;
+ $mailbox = $this->next(self::NEXT_SHOWCLOSED);
+ }
+ }
+
+ if ($mailbox) {
+ do {
+ if (!is_null($baseindex) &&
+ (!isset($this->_currstack[$baseindex]) ||
+ ($this->_currstack[$baseindex]['k'] != $basekey) ||
+ ($this->_currstack[$baseindex]['p'] != $baseparent))) {
+ break;
+ }
+
+ if ((($mask & self::FLIST_CONTAINER) ||
+ !$this->isContainer($mailbox)) &&
+ (($mask & self::FLIST_VFOLDER) ||
+ !$this->isVFolder($mailbox))) {
+ $ret_array[] = ($mask & self::FLIST_OB) ? $mailbox : $mailbox['v'];
+ }
+ } while (($mailbox = $this->next(self::NEXT_SHOWCLOSED)));
+ }
+
+ if (!is_null($diff_unsub)) {
+ $this->showUnsubscribed($diff_unsub);
+ }
+
+ return $ret_array;
+ }
+
+ /**
+ * Is the mailbox open in the sidebar?
+ *
+ * @param array $mbox A mailbox name.
+ *
+ * @return integer True if the mailbox is open in the sidebar.
+ */
+ public function isOpenSidebar($mbox)
+ {
+ switch ($GLOBALS['prefs']->getValue('nav_expanded_sidebar')) {
+ case self::OPEN_USER:
+ $this->_initExpandedList();
+ return !empty($this->_expanded[$mbox]);
+ break;
+
+ case self::OPEN_ALL:
+ return true;
+ break;
+
+ case self::OPEN_NONE:
+ default:
+ return false;
+ break;
+ }
+ }
+
+ /**
+ * Init frequently used element() data.
+ */
+ protected function _initElement()
+ {
+ global $prefs, $registry;
+
+ /* Initialize the user's identities. */
+ require_once 'Horde/Identity.php';
+ $identity = Identity::singleton(array('imp', 'imp'));
+
+ return array(
+ 'trash' => IMP::folderPref($prefs->getValue('trash_folder'), true),
+ 'draft' => IMP::folderPref($prefs->getValue('drafts_folder'), true),
+ 'spam' => IMP::folderPref($prefs->getValue('spam_folder'), true),
+ 'sent' => $identity->getAllSentmailFolders(),
+ 'image_dir' => $registry->getImageDir(),
+ );
+ }
+
+ /**
+ * Return extended information on an element.
+ *
+ * @param string $name The name of the tree element.
+ *
+ * @return array Returns the element with extended information, or false
+ * if not found. The information returned is as follows:
+ * <pre>
+ * 'alt' - The alt text for the icon.
+ * 'base_elt' - The return from get().
+ * 'children' - Does the element have children?
+ * 'container' - Is this a container element?
+ * 'editvfolder' - Can this virtual folder be edited?
+ * 'icon' - The name of the icon graphic to use.
+ * 'icondir' - The path of the icon directory.
+ * 'level' - The deepness level of this element.
+ * 'mbox_val' - A html-ized version of 'value'.
+ * 'msgs' - The number of total messages in the element (if polled).
+ * 'name' - A html-ized version of 'label'.
+ * 'parent' - The parent element value.
+ * 'polled' - Show polled information?
+ * 'recent' - The number of new messages in the element (if polled).
+ * 'special' - An integer mask indicating if this is a "special" element.
+ * 'specialvfolder' - Is this a "special" virtual folder?
+ * 'unseen' - The number of unseen messages in the element (if polled).
+ * 'user_icon' - Use a user defined icon?
+ * 'value' - The value of this element (i.e. element id).
+ * 'vfolder' - Is this a virtual folder?
+ * </pre>
+ */
+ public function element($mailbox)
+ {
+ static $elt;
+
+ $mailbox = $this->get($mailbox);
+ if (!$mailbox) {
+ return false;
+ }
+
+ if (!isset($elt)) {
+ $elt = $this->_initElement();
+ }
+
+ $row = array(
+ 'base_elt' => $mailbox,
+ 'children' => $this->hasChildren($mailbox),
+ 'container' => false,
+ 'editvfolder' => false,
+ 'icondir' => $elt['image_dir'],
+ 'iconopen' => null,
+ 'level' => $mailbox['c'],
+ 'mbox_val' => htmlspecialchars($mailbox['v']),
+ 'name' => htmlspecialchars($mailbox['l']),
+ 'parent' => $mailbox['p'],
+ 'polled' => false,
+ 'recent' => 0,
+ 'special' => 0,
+ 'specialvfolder' => false,
+ 'user_icon' => false,
+ 'value' => $mailbox['v'],
+ 'vfolder' => false,
+ );
+
+ $icon = $this->getCustomIcon($mailbox);
+
+ if (!$this->isContainer($mailbox)) {
+ /* We are dealing with mailboxes here.
+ * Determine if we need to poll this mailbox for new messages. */
+ if ($this->isPolled($mailbox)) {
+ /* If we need message information for this folder, update
+ * it now. */
+ $msgs_info = $this->getElementInfo($mailbox['v']);
+ if (!empty($msgs_info)) {
+ $row['polled'] = true;
+ if (!empty($msgs_info['recent'])) {
+ $row['recent'] = $msgs_info['recent'];
+ }
+ $row['msgs'] = $msgs_info['messages'];
+ $row['unseen'] = $msgs_info['unseen'];
+ }
+ }
+
+
+ switch ($mailbox['v']) {
+ case 'INBOX':
+ $row['icon'] = 'folders/inbox.png';
+ $row['alt'] = _("Inbox");
+ $row['special'] = self::SPECIAL_INBOX;
+ break;
+
+ case $elt['trash']:
+ if ($GLOBALS['prefs']->getValue('use_vtrash')) {
+ $row['icon'] = ($this->isOpen($mailbox)) ? 'folders/folder_open.png' : 'folders/folder.png';
+ $row['alt'] = _("Mailbox");
+ } else {
+ $row['icon'] = 'folders/trash.png';
+ $row['alt'] = _("Trash folder");
+ $row['special'] = self::SPECIAL_TRASH;
+ }
+ break;
+
+ case $elt['draft']:
+ $row['icon'] = 'folders/drafts.png';
+ $row['alt'] = _("Draft folder");
+ $row['special'] = self::SPECIAL_DRAFT;
+ break;
+
+ case $elt['spam']:
+ $row['icon'] = 'folders/spam.png';
+ $row['alt'] = _("Spam folder");
+ $row['special'] = self::SPECIAL_SPAM;
+ break;
+
+ default:
+ if (in_array($mailbox['v'], $elt['sent'])) {
+ $row['icon'] = 'folders/sent.png';
+ $row['alt'] = _("Sent mail folder");
+ $row['special'] = self::SPECIAL_SENT;
+ } else {
+ $row['icon'] = ($this->isOpen($mailbox)) ? 'folders/folder_open.png' : 'folders/folder.png';
+ $row['alt'] = _("Mailbox");
+ }
+ break;
+ }
+
+ /* Virtual folders. */
+ if ($this->isVFolder($mailbox)) {
+ $row['vfolder'] = true;
+ $row['editvfolder'] = $GLOBALS['imp_search']->isEditableVFolder($mailbox['v']);
+ if ($GLOBALS['imp_search']->isVTrashFolder($mailbox['v'])) {
+ $row['specialvfolder'] = true;
+ $row['icon'] = 'folders/trash.png';
+ $row['alt'] = _("Virtual Trash Folder");
+ } elseif ($GLOBALS['imp_search']->isVINBOXFolder($mailbox['v'])) {
+ $row['specialvfolder'] = true;
+ $row['icon'] = 'folders/inbox.png';
+ $row['alt'] = _("Virtual INBOX Folder");
+ }
+ }
+ } else {
+ /* We are dealing with folders here. */
+ $row['container'] = true;
+ if ($this->_forceopen && $this->isOpen($mailbox)) {
+ $row['icon'] = 'folders/folder_open.png';
+ $row['alt'] = _("Opened Folder");
+ } else {
+ $row['icon'] = 'folders/folder.png';
+ $row['iconopen'] = 'folders/folder_open.png';
+ $row['alt'] = ($this->_forceopen) ? _("Closed Folder") : _("Folder");
+ }
+ if ($this->isVFolder($mailbox)) {
+ $row['vfolder'] = true;
+ }
+ }
+
+ /* Overwrite the icon information now. */
+ if (!empty($icon)) {
+ $row['icon'] = $icon['icon'];
+ $row['icondir'] = $icon['icondir'];
+ if (!empty($icon['alt'])) {
+ $row['alt'] = $icon['alt'];
+ }
+ $row['iconopen'] = isset($icon['iconopen']) ? $icon['iconopen'] : null;
+ $row['user_icon'] = true;
+ }
+
+ return $row;
+ }
+
+ /**
+ * Sort a level in the tree.
+ *
+ * @param string $id The parent folder whose children need to be sorted.
+ */
+ protected function _sortLevel($id)
+ {
+ if ($this->_needSort($this->_tree[$id])) {
+ $this->_sortList($this->_parent[$id], ($id === self::BASE_ELT));
+ $this->_setNeedSort($this->_tree[$id], false);
+ $this->_changed = true;
+ }
+ }
+
+ /**
+ * Determines the mailbox name to create given a parent and the new name.
+ *
+ * @param string $parent The parent name (UTF7-IMAP).
+ * @param string $parent The new mailbox name (UTF7-IMAP).
+ *
+ * @return string The full path to the new mailbox.
+ * @throws Horde_Exception
+ */
+ public function createMailboxName($parent, $new)
+ {
+ $ns_info = (empty($parent)) ? $GLOBALS['imp_imap']->defaultNamespace() : $this->_getNamespace($parent);
+ if (is_null($ns_info)) {
+ if ($this->isNamespace($this->_tree[$parent])) {
+ $ns_info = $this->_getNamespace($new);
+ if (in_array($ns_info['type'], array('other', 'shared'))) {
+ return $new;
+ }
+ }
+ throw new Horde_Exception(_("Cannot directly create mailbox in this folder."), 'horde.error');
+ }
+
+ $mbox = $ns_info['name'];
+ if (!empty($parent)) {
+ $mbox .= substr_replace($parent, '', 0, strlen($ns_info['name']));
+ $mbox = rtrim($mbox, $ns_info['delimiter']) . $ns_info['delimiter'];
+ }
+ return $mbox . $new;
+ }
+}
$_SESSION['imp']['search'] = array('q' => array());
}
if (!$no_vf) {
- $imaptree = &IMP_IMAP_Tree::singleton();
+ $imaptree = &IMP_Imap_Tree::singleton();
foreach ($this->_getVFolderList() as $key => $val) {
if (!empty($val['vfolder']) &&
!$this->isVTrashFolder($key) &&
unset($vfolders[$id]);
$this->_saveVFolderList($vfolders);
if (!$no_delete) {
- $imaptree = &IMP_IMAP_Tree::singleton();
+ $imaptree = &IMP_Imap_Tree::singleton();
$imaptree->delete($id);
}
}
$this->_saveVFolderList($vfolders);
}
- $imaptree = &IMP_IMAP_Tree::singleton();
+ $imaptree = &IMP_Imap_Tree::singleton();
$imaptree->insertVFolders(array($id => $label));
return $id;
*/
public function createVINBOXFolder()
{
- /* Initialize IMP_IMAP_Tree. */
- $imaptree = &IMP_IMAP_Tree::singleton();
+ /* Initialize IMP_Imap_Tree. */
+ $imaptree = &IMP_Imap_Tree::singleton();
/* Delete the current Virtual Inbox folder, if it exists. */
$vinbox_id = $GLOBALS['prefs']->getValue('vinbox_id');
/* Create folder search list. */
switch ($args['searchfolder']) {
case 'all':
- $imptree = &IMP_IMAP_Tree::singleton();
+ $imptree = &IMP_Imap_Tree::singleton();
$folder_list = $imptree->folderList();
break;
/* Get unseen/thread information. */
if (is_null($search_id)) {
- $imptree = &IMP_IMAP_Tree::singleton();
+ $imptree = &IMP_Imap_Tree::singleton();
$info = $imptree->getElementInfo($mbox);
if (!empty($info)) {
$md->unseen = $info['unseen'];
if ($sortpref['by'] == Horde_Imap_Client::SORT_THREAD) {
$threadob = $imp_mailbox->getThreadOb();
- $imp_thread = new IMP_IMAP_Thread($threadob);
+ $imp_thread = new IMP_Imap_Thread($threadob);
$md->thread = $imp_thread->getThreadTreeOb($msglist, $sortpref['dir']);
}
} else {
$app_name = $GLOBALS['registry']->get('name');
require_once dirname(__FILE__) . '/IMAP.php';
- $servers = IMP_IMAP::loadServerConfig();
+ $servers = IMP_Imap::loadServerConfig();
$server_list = array();
foreach ($servers as $key => $val) {
$server_list[$key] = $val['name'];
if (IMP::checkAuthentication(true)) {
$imp_folder = &IMP_Folder::singleton();
$imp_folder->clearFlistCache();
- $imaptree = &IMP_IMAP_Tree::singleton();
+ $imaptree = &IMP_Imap_Tree::singleton();
$imaptree->init();
$imp_search = new IMP_Search();
$imp_search->sessionSetup(true);
* $session_control - Sets special session control limitations
*
* Global variables defined:
- * $imp_imap - An IMP_IMAP object
+ * $imp_imap - An IMP_Imap object
* $imp_mbox - Current mailbox information
* $imp_notify - A Notification_Listener_Mobile object
* $imp_search - An IMP_Search object
// Initialize global $imp_imap object.
if (!isset($GLOBALS['imp_imap'])) {
- $GLOBALS['imp_imap'] = new IMP_IMAP();
+ $GLOBALS['imp_imap'] = new IMP_Imap();
}
// Start compression.
if ($prefs->isDirty('subscribe') || $prefs->isDirty('tree_view')) {
$imp_folder = &IMP_Folder::singleton();
$imp_folder->clearFlistCache();
- $imaptree = &IMP_IMAP_Tree::singleton();
+ $imaptree = &IMP_Imap_Tree::singleton();
$imaptree->init();
}
/* Get thread object, if necessary. */
if ($sortpref['by'] == Horde_Imap_Client::SORT_THREAD) {
- $imp_thread = new IMP_IMAP_Thread($imp_mailbox->getThreadOb());
+ $imp_thread = new IMP_Imap_Thread($imp_mailbox->getThreadOb());
$threadtree = $imp_thread->getThreadImageTree(reset($mbox_info['uids']), $sortpref['dir']);
}
$index_array = $imp_mailbox->getIMAPIndex();
$thread = $threadob->getThread($index_array['index']);
- $imp_thread = new IMP_IMAP_Thread($threadob);
+ $imp_thread = new IMP_Imap_Thread($threadob);
$threadtree = $imp_thread->getThreadImageTree($thread, false);
$loop_array = array($imp_mbox['mailbox'] => $thread);
} else {